EncryptedFileChannel
An open source drop-in replacement for Java’s FileChannel that transparently encrypts and decrypts file data
using Google Tink.
Originally developed for a custom Apache Lucene store plugin, it allows encrypted index and transaction log files
without changing Lucene’s logic or APIs.
Features
- Extends
java.nio.channels.FileChannel- but not all methods are implemented - Transparent AES-256-GCM-HKDF streaming encryption (via Google Tink)
- Supports random access, append, and positional writes
- Thread-safe and atomic writes
- Tested with JUnit for correctness and concurrency safety
Usage
Gradle Integration
repositories {
maven {
url "https://nexus.karakun.com/repository/maven-public-releases/"
}
}
dependencies {
implementation 'com.karakun:encrypted-filechannel:2.1.0'
}Of course, it can also be integrated into Maven with the appropriate syntax.
Read and Write Channel
private static final byte[] ENCRYPTION_KEY = Base64.getUrlDecoder().decode("cxGrfBkPPMpbUGKUU1iaBW8RCDeID8-uR40jslBQaMY=");
private void readAndWrite() throws IOException {
Path tmpFile = Files.createTempDirectory(Scratch.class.getName()).resolve("writeAndRead.tlog");
final String writeString = "Hello world!";
try (final FileChannel fileChannel = EncryptedFileChannel.open(tmpFile, ENCRYPTION_KEY, CREATE_NEW)) {
fileChannel.write(ByteBuffer.wrap(writeString.getBytes()));
assertEquals(writeString.getBytes().length, fileChannel.size(), "size");
}
try (final FileChannel fileChannel = EncryptedFileChannel.open(tmpFile, ENCRYPTION_KEY, READ)) {
final ByteBuffer byteBuffer = ByteBuffer.allocate(writeString.getBytes().length);
fileChannel.read(byteBuffer, 0);
assertEquals(writeString, new String(byteBuffer.array()));
}
// Try reading with a non-decrypting FileChannel.
try (final FileChannel fileChannel = FileChannel.open(tmpFile, READ)) {
final ByteBuffer byteBuffer = ByteBuffer.allocate(writeString.getBytes().length);
fileChannel.read(byteBuffer, 0);
assertNotEquals(writeString, new String(byteBuffer.array()));
}
}Security Notes
- Do not store encryption keys as
String. Usebyte[]or aKeysetHandle. - Strings are immutable and may remain in the JVM’s string pool, while byte[] can be cleared from memory.
- Manage keysets securely (for example, using Tinkey, Vault, or a KMS).
Why Tink
Google Tink enforces safe defaults, authenticated encryption, and key rotation.
It helps prevent common cryptographic mistakes such as nonce reuse, missing authentication tags, or unsafe cipher modes.
In short: don’t roll your own crypto!
Build and Test
Requires Java 21 and Maven 3.9+.
mvn clean packageContinuous integration runs automatically on GitHub Actions with Java 21 (Temurin).
Misc
There is also a tech article about this component on Karakuns dev hub.