Skip to content

Commit

Permalink
Avoid ByteBuffer#asReadOnlyBuffer() (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
overheadhunter authored Feb 7, 2022
1 parent 96f00c9 commit 0830881
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,12 @@ void encryptChunk(ByteBuffer cleartextChunk, ByteBuffer ciphertextChunk, long ch
final Cipher cipher = CipherSupplier.AES_CTR.forEncryption(fk, new IvParameterSpec(nonce));
ciphertextChunk.put(nonce);
assert ciphertextChunk.remaining() >= cipher.getOutputSize(cleartextChunk.remaining()) + MAC_SIZE;
int bytesEncrypted = cipher.doFinal(cleartextChunk, ciphertextChunk);
cipher.doFinal(cleartextChunk, ciphertextChunk);

// mac:
final ByteBuffer ciphertextBuf = ciphertextChunk.asReadOnlyBuffer();
ciphertextBuf.position(NONCE_SIZE).limit(NONCE_SIZE + bytesEncrypted);
byte[] authenticationCode = calcChunkMac(headerNonce, chunkNumber, nonce, ciphertextBuf);
ByteBuffer nonceAndPayload = ciphertextChunk.duplicate();
nonceAndPayload.flip();
byte[] authenticationCode = calcChunkMac(headerNonce, chunkNumber, nonceAndPayload);
assert authenticationCode.length == MAC_SIZE;
ciphertextChunk.put(authenticationCode);
} catch (ShortBufferException e) {
Expand All @@ -134,12 +134,10 @@ void decryptChunk(ByteBuffer ciphertextChunk, ByteBuffer cleartextChunk, Destroy
try (DestroyableSecretKey fk = fileKey.copy()) {
// nonce:
final byte[] nonce = new byte[NONCE_SIZE];
final ByteBuffer chunkNonceBuf = ciphertextChunk.asReadOnlyBuffer();
chunkNonceBuf.position(0).limit(NONCE_SIZE);
chunkNonceBuf.get(nonce);
ciphertextChunk.get(nonce, 0, NONCE_SIZE);

// payload:
final ByteBuffer payloadBuf = ciphertextChunk.asReadOnlyBuffer();
final ByteBuffer payloadBuf = ciphertextChunk.duplicate();
payloadBuf.position(NONCE_SIZE).limit(ciphertextChunk.limit() - MAC_SIZE);

// payload:
Expand All @@ -157,37 +155,30 @@ void decryptChunk(ByteBuffer ciphertextChunk, ByteBuffer cleartextChunk, Destroy
boolean checkChunkMac(byte[] headerNonce, long chunkNumber, ByteBuffer chunkBuf) {
assert chunkBuf.remaining() >= NONCE_SIZE + MAC_SIZE;

// get three components: nonce + payload + mac
final ByteBuffer chunkNonceBuf = chunkBuf.asReadOnlyBuffer();
chunkNonceBuf.position(0).limit(NONCE_SIZE);
final ByteBuffer payloadBuf = chunkBuf.asReadOnlyBuffer();
payloadBuf.position(NONCE_SIZE).limit(chunkBuf.limit() - MAC_SIZE);
final ByteBuffer expectedMacBuf = chunkBuf.asReadOnlyBuffer();
// get nonce + payload
final ByteBuffer nonceAndPayload = chunkBuf.duplicate();
nonceAndPayload.position(0).limit(chunkBuf.limit() - MAC_SIZE);
final ByteBuffer expectedMacBuf = chunkBuf.duplicate();
expectedMacBuf.position(chunkBuf.limit() - MAC_SIZE);

// get nonce:
final byte[] chunkNonce = new byte[NONCE_SIZE];
chunkNonceBuf.get(chunkNonce);

// get expected MAC:
final byte[] expectedMac = new byte[MAC_SIZE];
expectedMacBuf.get(expectedMac);

// get actual MAC:
final byte[] calculatedMac = calcChunkMac(headerNonce, chunkNumber, chunkNonce, payloadBuf);
final byte[] calculatedMac = calcChunkMac(headerNonce, chunkNumber, nonceAndPayload);

// time-constant equality check of two MACs:
return MessageDigest.isEqual(expectedMac, calculatedMac);
}

private byte[] calcChunkMac(byte[] headerNonce, long chunkNumber, byte[] chunkNonce, ByteBuffer ciphertext) {
private byte[] calcChunkMac(byte[] headerNonce, long chunkNumber, ByteBuffer nonceAndCiphertext) {
try (DestroyableSecretKey mk = masterkey.getMacKey()) {
final byte[] chunkNumberBigEndian = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).order(ByteOrder.BIG_ENDIAN).putLong(chunkNumber).array();
final Mac mac = MacSupplier.HMAC_SHA256.withKey(mk);
mac.update(headerNonce);
mac.update(chunkNumberBigEndian);
mac.update(chunkNonce);
mac.update(ciphertext);
mac.update(nonceAndCiphertext);
return mac.doFinal();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public FileHeader decryptHeader(ByteBuffer ciphertextHeaderBuf) throws Authentic
if (ciphertextHeaderBuf.remaining() < FileHeaderImpl.SIZE) {
throw new IllegalArgumentException("Malformed ciphertext header");
}
ByteBuffer buf = ciphertextHeaderBuf.asReadOnlyBuffer();
ByteBuffer buf = ciphertextHeaderBuf.duplicate();
byte[] nonce = new byte[FileHeaderImpl.NONCE_LEN];
buf.position(FileHeaderImpl.NONCE_POS);
buf.get(nonce);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,10 @@ void decryptChunk(ByteBuffer ciphertextChunk, ByteBuffer cleartextChunk, long ch
try (DestroyableSecretKey fk = fileKey.copy()) {
// nonce:
final byte[] nonce = new byte[GCM_NONCE_SIZE];
final ByteBuffer chunkNonceBuf = ciphertextChunk.asReadOnlyBuffer();
chunkNonceBuf.position(0).limit(GCM_NONCE_SIZE);
chunkNonceBuf.get(nonce);
ciphertextChunk.get(nonce, 0, GCM_NONCE_SIZE);

// payload:
final ByteBuffer payloadBuf = ciphertextChunk.asReadOnlyBuffer();
final ByteBuffer payloadBuf = ciphertextChunk.duplicate();
payloadBuf.position(GCM_NONCE_SIZE);
assert payloadBuf.remaining() >= GCM_TAG_SIZE;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public FileHeader decryptHeader(ByteBuffer ciphertextHeaderBuf) throws Authentic
if (ciphertextHeaderBuf.remaining() < FileHeaderImpl.SIZE) {
throw new IllegalArgumentException("Malformed ciphertext header");
}
ByteBuffer buf = ciphertextHeaderBuf.asReadOnlyBuffer();
ByteBuffer buf = ciphertextHeaderBuf.duplicate();
byte[] nonce = new byte[FileHeaderImpl.NONCE_LEN];
buf.position(FileHeaderImpl.NONCE_POS);
buf.get(nonce);
Expand Down

0 comments on commit 0830881

Please sign in to comment.