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 @@ -11,6 +11,7 @@ Function("generateKey", generateKey) Function("encrypt", encrypt) + Function("decrypt", decrypt) } } @@ -51,6 +52,20 @@ sealedData.copyBytes(to: destination.rawBufferPtr()) } +private func decrypt(rawKey: Uint8Array, + sealedData: Uint8Array, + destination: Uint8Array) throws { + guard destination.byteLength == sealedData.byteLength - IV_LENGTH - TAG_LENGTH + else { + throw InvalidDataLengthException() + } + + let key = SymmetricKey(data: rawKey.data()) + let sealedBox = try AES.GCM.SealedBox(combined: sealedData.data()) + let plaintext = try AES.GCM.open(sealedBox, using: key) + plaintext.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,11 @@ AESCryptoModule.encrypt(key, data, sealedDataBuffer); return sealedDataBuffer; } + +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); + return plaintextBuffer; +}