Page MenuHomePhabricator

D7008.id23543.diff
No OneTemporary

D7008.id23543.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(ciphertext, position = IV_LENGTH, size = ciphertext.size)
}
+ /**
+ * Decrypts given [ciphertext] using provided key and stores decrypted
+ * plaintext in the [destination] array.
+ *
+ * @param rawKey AES-256 key bytes. Must be of length [KEY_SIZE]
+ * @param ciphertext 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,
+ ciphertext: Uint8Array,
+ destination: Uint8Array
+ ) {
+ if (ciphertext.byteLength <= IV_LENGTH + TAG_LENGTH ||
+ destination.byteLength < ciphertext.byteLength - IV_LENGTH - TAG_LENGTH) {
+ throw InvalidDataLengthException()
+ }
+ val key = rawKey.toAESSecretKey()
+ val input = ciphertext.toDirectBuffer()
+ val iv = ByteArray(IV_LENGTH).also(input::get)
+ val ciphertextBytes = ByteArray(input.remaining()).also(input::get)
+ val plaintext = decryptAES(ciphertextBytes, key, iv)
+
+ destination.write(plaintext, position = 0, size = plaintext.size)
+ }
+
// endregion
}
@@ -99,6 +128,22 @@
return Pair(iv, ciphertext)
}
+/**
+ * Does the reverse of the [encryptAES] function.
+ * Decrypts the [ciphertext] with given [key] and [iv]
+ */
+private fun decryptAES(
+ ciphertext: 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(ciphertext)
+}
+
// 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
@@ -1,7 +1,6 @@
// @flow
import { requireNativeModule } from 'expo-modules-core';
-import invariant from 'invariant';
const KEY_SIZE = 32;
const IV_LENGTH = 12;
@@ -34,7 +33,6 @@
}
export function decrypt(key: Uint8Array, data: Uint8Array): Uint8Array {
- invariant(AESCryptoModule.decrypt, 'AESCrypto.decrypt is not implemented');
const plaintext = new Uint8Array(data.length - IV_LENGTH - TAG_LENGTH);
AESCryptoModule.decrypt(key, data, plaintext);
return plaintext;

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 30, 8:24 AM (21 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2600256
Default Alt Text
D7008.id23543.diff (3 KB)

Event Timeline