Skip to content

Encryption output gets truncated because of incorrect offset handling by FrameEncryptionHandler #2112

Closed
@alex122830

Description

@alex122830

Problem:

The method FrameEncryptionHandler::processBytes behaves incorrectly when its parameter off is not zero. It leads to the truncated encryption.
This is a unit test that reproduces the issue. Notice that if startOffset was 0, then the test would pass.

    @Test
    public void testStream() throws Exception {
        var testDataString = "Hello, World! ".repeat(10_000);

        int startOffset = 100; // The data will start from this offset
        byte[] inputData = new byte[10_000];
        System.arraycopy(
                testDataString.getBytes(StandardCharsets.UTF_8),
                0,
                inputData,
                startOffset,
                inputData.length - startOffset);
        int originalLength = inputData.length - startOffset;

        // Generate a random AES key
        var rnd = new SecureRandom();
        byte[] rawKey = new byte[16];
        rnd.nextBytes(rawKey);
        var cryptoKey = new SecretKeySpec(rawKey, "AES");

        // Create a keyring using the generated AES key
        var materialProviders = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        var keyringInput = CreateRawAesKeyringInput.builder()
                .wrappingKey(ByteBuffer.wrap(cryptoKey.getEncoded()))
                .keyNamespace("Example")
                .keyName("RandomKey")
                .wrappingAlg(AesWrappingAlg.ALG_AES128_GCM_IV12_TAG16)
                .build();
        var keyring = materialProviders.CreateRawAesKeyring(keyringInput);
        var crypto = AwsCrypto.standard();

        // Encrypt the data
        byte[] encryptedData;
        try (var os = new ByteArrayOutputStream()) {
            try (var cryptoOutput = crypto.createEncryptingStream(keyring, os, Map.of())) {
                cryptoOutput.write(inputData, startOffset, inputData.length - startOffset);
            }
            encryptedData = os.toByteArray();
        }

        // Decrypt the data
        int decryptedLength = 0;
        byte[] decryptedData = new byte[inputData.length];
        try (var is = new ByteArrayInputStream(encryptedData);
             var cryptoInput = crypto.createDecryptingStream(keyring, is)) {
            int offset = startOffset;
            do {
                int bytesRead = cryptoInput.read(decryptedData, offset, decryptedData.length - offset);
                if (bytesRead <= 0) {
                    break; // End of stream
                }
                offset += bytesRead;
                decryptedLength += bytesRead;
            } while (true);
        }
        assertEquals(originalLength, decryptedLength);
        assertArrayEquals(inputData, decryptedData);
    }

Suggested solution:

--- a/src/main/java/com/amazonaws/encryptionsdk/internal/FrameEncryptionHandler.java
+++ b/src/main/java/com/amazonaws/encryptionsdk/internal/FrameEncryptionHandler.java
@@ -116,7 +116,7 @@ class FrameEncryptionHandler implements CryptoHandler {
       // update offset by the size of bytes being encrypted.
       offset += size;
       // update size to the remaining bytes starting at offset.
-      size = len - offset;
+      size = len - offset + off;
     }
 
     return new ProcessingSummary(actualOutLen, len);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions