Skip to content

Commit

Permalink
[MOB-9235] Fix variable IV length issue (#853)
Browse files Browse the repository at this point in the history
* [MOB-9235] Fix variable IV length issue

* Fix changelog

* revert whitespace
  • Loading branch information
sumeruchat authored Jan 2, 2025
1 parent df90443 commit 897fd9e
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 13 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).


## [3.5.6]

#### Fixed
- Fixed IV length handling in encryption to properly support both modern (GCM) and legacy (CBC) encryption modes.

## [3.5.5]

#### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class IterableDataEncryptor {
private const val TRANSFORMATION_LEGACY = "AES/CBC/PKCS5Padding"
private const val ITERABLE_KEY_ALIAS = "iterable_encryption_key"
private const val GCM_TAG_LENGTH = 128
private const val IV_LENGTH = 16
private const val GCM_IV_LENGTH = 12
private const val CBC_IV_LENGTH = 16
private val TEST_KEYSTORE_PASSWORD = "test_password".toCharArray()

private val keyStore: KeyStore by lazy {
Expand Down Expand Up @@ -132,11 +133,12 @@ class IterableDataEncryptor {
encryptLegacy(data)
}

// Combine isModern flag, IV, and encrypted data
val combined = ByteArray(1 + encryptedData.iv.size + encryptedData.data.size)
// Combine isModern flag, IV length, IV, and encrypted data
val combined = ByteArray(1 + 1 + encryptedData.iv.size + encryptedData.data.size)
combined[0] = if (encryptedData.isModernEncryption) 1 else 0
System.arraycopy(encryptedData.iv, 0, combined, 1, encryptedData.iv.size)
System.arraycopy(encryptedData.data, 0, combined, 1 + encryptedData.iv.size, encryptedData.data.size)
combined[1] = encryptedData.iv.size.toByte() // Store IV length
System.arraycopy(encryptedData.iv, 0, combined, 2, encryptedData.iv.size)
System.arraycopy(encryptedData.data, 0, combined, 2 + encryptedData.iv.size, encryptedData.data.size)

return Base64.encodeToString(combined, Base64.NO_WRAP)
} catch (e: Exception) {
Expand All @@ -153,8 +155,9 @@ class IterableDataEncryptor {

// Extract components
val isModern = combined[0] == 1.toByte()
val iv = combined.copyOfRange(1, 1 + IV_LENGTH)
val encrypted = combined.copyOfRange(1 + IV_LENGTH, combined.size)
val ivLength = combined[1].toInt()
val iv = combined.copyOfRange(2, 2 + ivLength)
val encrypted = combined.copyOfRange(2 + ivLength, combined.size)

val encryptedData = EncryptedData(encrypted, iv, isModern)

Expand Down Expand Up @@ -187,16 +190,15 @@ class IterableDataEncryptor {
}

val cipher = Cipher.getInstance(TRANSFORMATION_MODERN)
val iv = generateIV()
val spec = GCMParameterSpec(GCM_TAG_LENGTH, iv)
cipher.init(Cipher.ENCRYPT_MODE, getKey(), spec)
cipher.init(Cipher.ENCRYPT_MODE, getKey())
val iv = cipher.iv
val encrypted = cipher.doFinal(data)
return EncryptedData(encrypted, iv, true)
}

private fun encryptLegacy(data: ByteArray): EncryptedData {
val cipher = Cipher.getInstance(TRANSFORMATION_LEGACY)
val iv = generateIV()
val iv = generateIV(isModern = false)
val spec = IvParameterSpec(iv)
cipher.init(Cipher.ENCRYPT_MODE, getKey(), spec)
val encrypted = cipher.doFinal(data)
Expand All @@ -222,8 +224,9 @@ class IterableDataEncryptor {
return cipher.doFinal(encryptedData.data)
}

private fun generateIV(): ByteArray {
val iv = ByteArray(IV_LENGTH)
private fun generateIV(isModern: Boolean = false): ByteArray {
val length = if (isModern) GCM_IV_LENGTH else CBC_IV_LENGTH
val iv = ByteArray(length)
SecureRandom().nextBytes(iv)
return iv
}
Expand Down

0 comments on commit 897fd9e

Please sign in to comment.