@@ -23,7 +23,8 @@ class IterableDataEncryptor {
2323 private const val TRANSFORMATION_LEGACY = " AES/CBC/PKCS5Padding"
2424 private const val ITERABLE_KEY_ALIAS = " iterable_encryption_key"
2525 private const val GCM_TAG_LENGTH = 128
26- private const val IV_LENGTH = 16
26+ private const val GCM_IV_LENGTH = 12
27+ private const val CBC_IV_LENGTH = 16
2728 private val TEST_KEYSTORE_PASSWORD = " test_password" .toCharArray()
2829
2930 private val keyStore: KeyStore by lazy {
@@ -132,11 +133,12 @@ class IterableDataEncryptor {
132133 encryptLegacy(data)
133134 }
134135
135- // Combine isModern flag, IV, and encrypted data
136- val combined = ByteArray (1 + encryptedData.iv.size + encryptedData.data.size)
136+ // Combine isModern flag, IV length, IV , and encrypted data
137+ val combined = ByteArray (1 + 1 + encryptedData.iv.size + encryptedData.data.size)
137138 combined[0 ] = if (encryptedData.isModernEncryption) 1 else 0
138- System .arraycopy(encryptedData.iv, 0 , combined, 1 , encryptedData.iv.size)
139- System .arraycopy(encryptedData.data, 0 , combined, 1 + encryptedData.iv.size, encryptedData.data.size)
139+ combined[1 ] = encryptedData.iv.size.toByte() // Store IV length
140+ System .arraycopy(encryptedData.iv, 0 , combined, 2 , encryptedData.iv.size)
141+ System .arraycopy(encryptedData.data, 0 , combined, 2 + encryptedData.iv.size, encryptedData.data.size)
140142
141143 return Base64 .encodeToString(combined, Base64 .NO_WRAP )
142144 } catch (e: Exception ) {
@@ -153,8 +155,9 @@ class IterableDataEncryptor {
153155
154156 // Extract components
155157 val isModern = combined[0 ] == 1 .toByte()
156- val iv = combined.copyOfRange(1 , 1 + IV_LENGTH )
157- val encrypted = combined.copyOfRange(1 + IV_LENGTH , combined.size)
158+ val ivLength = combined[1 ].toInt()
159+ val iv = combined.copyOfRange(2 , 2 + ivLength)
160+ val encrypted = combined.copyOfRange(2 + ivLength, combined.size)
158161
159162 val encryptedData = EncryptedData (encrypted, iv, isModern)
160163
@@ -187,16 +190,15 @@ class IterableDataEncryptor {
187190 }
188191
189192 val cipher = Cipher .getInstance(TRANSFORMATION_MODERN )
190- val iv = generateIV()
191- val spec = GCMParameterSpec (GCM_TAG_LENGTH , iv)
192- cipher.init (Cipher .ENCRYPT_MODE , getKey(), spec)
193+ cipher.init (Cipher .ENCRYPT_MODE , getKey())
194+ val iv = cipher.iv
193195 val encrypted = cipher.doFinal(data)
194196 return EncryptedData (encrypted, iv, true )
195197 }
196198
197199 private fun encryptLegacy (data : ByteArray ): EncryptedData {
198200 val cipher = Cipher .getInstance(TRANSFORMATION_LEGACY )
199- val iv = generateIV()
201+ val iv = generateIV(isModern = false )
200202 val spec = IvParameterSpec (iv)
201203 cipher.init (Cipher .ENCRYPT_MODE , getKey(), spec)
202204 val encrypted = cipher.doFinal(data)
@@ -222,8 +224,9 @@ class IterableDataEncryptor {
222224 return cipher.doFinal(encryptedData.data)
223225 }
224226
225- private fun generateIV (): ByteArray {
226- val iv = ByteArray (IV_LENGTH )
227+ private fun generateIV (isModern : Boolean = false): ByteArray {
228+ val length = if (isModern) GCM_IV_LENGTH else CBC_IV_LENGTH
229+ val iv = ByteArray (length)
227230 SecureRandom ().nextBytes(iv)
228231 return iv
229232 }
0 commit comments