diff --git a/native/expo-modules/aes-crypto/ios/AESCryptoModule.swift b/native/expo-modules/aes-crypto/ios/AESCryptoModule.swift --- a/native/expo-modules/aes-crypto/ios/AESCryptoModule.swift +++ b/native/expo-modules/aes-crypto/ios/AESCryptoModule.swift @@ -10,6 +10,7 @@ Function("generateKey", generateKey) Function("encrypt", encrypt) + Function("decrypt", decrypt) } } @@ -48,6 +49,31 @@ ciphertext.copyBytes(to: destination.rawBufferPtr()) } +private func decrypt(rawKey: Uint8Array, + ciphertext: Uint8Array, + destination: Uint8Array) throws { + guard ciphertext.byteLength > IV_LENGTH + TAG_LENGTH, + destination.byteLength >= ciphertext.byteLength - IV_LENGTH - TAG_LENGTH + else { + throw InvalidDataLengthException() + } + + let key = SymmetricKey(data: rawKey.data()) + let ciphertextData = ciphertext.data() + + let iv = ciphertextData.prefix(IV_LENGTH) + let tag = ciphertextData.suffix(TAG_LENGTH) + let ciphertextContent = ciphertextData + .dropFirst(IV_LENGTH) + .dropLast(TAG_LENGTH) + + let sealedBox = try AES.GCM.SealedBox(nonce: AES.GCM.Nonce(data: iv), + ciphertext: ciphertextContent, + tag: tag) + let decryptedData = try AES.GCM.open(sealedBox, using: key) + decryptedData.copyBytes(to: destination.rawBufferPtr()) +} + // MARK: - Utilities extension TypedArray { 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 @@ -14,6 +14,11 @@ data: Uint8Array, destination: Uint8Array, ) => void, + +decrypt: ( + key: Uint8Array, + data: Uint8Array, + destination: Uint8Array, + ) => void, } = requireNativeModule('AESCrypto'); export function generateKey(): Uint8Array { @@ -28,3 +33,10 @@ AESCryptoModule.encrypt(key, data, ciphertext); return ciphertext; } + +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; +}