Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using GCM decrypting the file header fails on Android API level pre 29 (version 9.0) #24

Closed
SailReal opened this issue Aug 24, 2021 · 0 comments · Fixed by #25
Closed
Labels

Comments

@SailReal
Copy link
Member

cipher.getOutputSize(ciphertext.size) with a ciphertext of 22 bytes using AES/GCM/NoPadding should return 6 bytes. This does not apply for devices on API version pre 29. There it is 16 bytes more (22).

Also the output buffer needs 16 more bytes than the plaintext has on Android pre 29 whereas on later Android versions like e.g. API level 29 this problem is fixed. On pre 29, when the output buffer has the expected size, a ShortBufferException is thrown.

Created a test repo to reproduce it and created a bug report too, but I don't think that Google will fix this problem anytime soon.

@Test
fun worksOnAPI26() {
    val input = "abcdef" // 6 bytes

    val key = ByteArray(16)
    SecureRandom().nextBytes(key)

    val cipher = Cipher.getInstance("AES/GCM/NoPadding")
    cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"))

    val ciphertext = cipher.doFinal(input.toByteArray())
    val iv = cipher.iv

    cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), GCMParameterSpec(128, iv))

    val payloadCleartextBuf = ByteBuffer.allocate(22) // should be 6 bytes
    assert(
        cipher.getOutputSize(ciphertext.size) == 22 // // should be 6 bytes
    )

    val decrypted = cipher.doFinal(ByteBuffer.wrap(ciphertext), payloadCleartextBuf)
    assert(decrypted == 6)

    payloadCleartextBuf.flip()

    println("plaintext : " + String(payloadCleartextBuf.array()))
}


@Test
fun worksOnAPI30() {
    val input = "abcdef" // 6 bytes

    val key = ByteArray(16)
    SecureRandom().nextBytes(key)

    val cipher = Cipher.getInstance("AES/GCM/NoPadding")
    cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"))

    val ciphertext = cipher.doFinal(input.toByteArray())
    val iv = cipher.iv

    cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), GCMParameterSpec(128, iv))

    val payloadCleartextBuf = ByteBuffer.allocate(6)
    assert(cipher.getOutputSize(ciphertext.size) == 6)

    val decrypted = cipher.doFinal(ByteBuffer.wrap(ciphertext), payloadCleartextBuf)
    assert(decrypted == 6)

    payloadCleartextBuf.flip()

    println("plaintext : " + String(payloadCleartextBuf.array()))
}

worksOnAPI30 throws the ShortBufferException on Android API level pre 29 (after removing the assertions otherwise the assertion will fail before).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant