Page MenuHomePhabricator

D7008.id23856.diff
No OneTemporary

D7008.id23856.diff

diff --git a/native/expo-modules/aes-crypto/android/src/main/java/app/comm/android/aescrypto/AESCryptoModule.kt b/native/expo-modules/aes-crypto/android/src/main/java/app/comm/android/aescrypto/AESCryptoModule.kt
--- a/native/expo-modules/aes-crypto/android/src/main/java/app/comm/android/aescrypto/AESCryptoModule.kt
+++ b/native/expo-modules/aes-crypto/android/src/main/java/app/comm/android/aescrypto/AESCryptoModule.kt
@@ -8,6 +8,7 @@
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
+import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec
private const val ALGORITHM_AES = "AES"
@@ -24,6 +25,7 @@
Function("generateKey", this@AESCryptoModule::generateKey)
Function("encrypt", this@AESCryptoModule::encrypt)
+ Function("decrypt", this@AESCryptoModule::decrypt)
}
// region Function implementations
@@ -75,6 +77,33 @@
destination.write(ciphertextWithTag, IV_LENGTH, ciphertextWithTag.size)
}
+ /**
+ * Decrypts given [sealedData] using provided key and stores decrypted
+ * plaintext in the [destination] array.
+ *
+ * @param rawKey AES-256 key bytes. Must be of length [KEY_SIZE]
+ * @param sealedData Typed array consisting of 12-byte IV, followed by
+ * actual ciphertext content and ending with 16-byte GCM tag.
+ * @param destination should be of ciphertext content length
+ */
+ private fun decrypt(
+ rawKey: Uint8Array,
+ sealedData: Uint8Array,
+ destination: Uint8Array
+ ) {
+ if (destination.byteLength
+ != sealedData.byteLength - IV_LENGTH - TAG_LENGTH) {
+ throw InvalidDataLengthException()
+ }
+ val key = rawKey.toAESSecretKey()
+ val input = sealedData.toDirectBuffer()
+ val iv = ByteArray(IV_LENGTH).also(input::get)
+ val ciphertextWithTagBytes = ByteArray(input.remaining()).also(input::get)
+ val plaintext = decryptAES(ciphertextWithTagBytes, key, iv)
+
+ destination.write(plaintext, position = 0, size = plaintext.size)
+ }
+
// endregion
}
@@ -99,6 +128,22 @@
return Pair(iv, ciphertextWithTag)
}
+/**
+ * Does the reverse of the [encryptAES] function.
+ * Decrypts the [ciphertext] with given [key] and [iv]
+ */
+private fun decryptAES(
+ ciphertextWithTag: ByteArray,
+ key: SecretKey,
+ iv: ByteArray
+): ByteArray {
+ val spec = GCMParameterSpec(TAG_LENGTH * 8, iv)
+ val cipher = Cipher.getInstance(CIPHER_TRANSFORMATION_NAME).apply {
+ init(Cipher.DECRYPT_MODE, key, spec)
+ }
+ return cipher.doFinal(ciphertextWithTag)
+}
+
// endregion
// region Utility extension functions
diff --git a/native/utils/aes-crypto-module.js b/native/utils/aes-crypto-module.js
--- a/native/utils/aes-crypto-module.js
+++ b/native/utils/aes-crypto-module.js
@@ -34,7 +34,6 @@
}
export function decrypt(key: Uint8Array, data: Uint8Array): Uint8Array {
- invariant(AESCryptoModule.decrypt, 'AESCrypto.decrypt is not implemented');
invariant(data.length >= IV_LENGTH + TAG_LENGTH, 'Invalid data length');
const plaintextBuffer = new Uint8Array(data.length - IV_LENGTH - TAG_LENGTH);
AESCryptoModule.decrypt(key, data, plaintextBuffer);

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 26, 8:00 PM (19 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2585967
Default Alt Text
D7008.id23856.diff (3 KB)

Event Timeline