Page MenuHomePhabricator

D7005.id23841.diff
No OneTemporary

D7005.id23841.diff

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
@@ -2,12 +2,15 @@
import CryptoKit
private let KEY_SIZE = 32 // bytes
+private let IV_LENGTH = 12 // bytes, IV - unique Initialization Vector (nonce)
+private let TAG_LENGTH = 16 // bytes - GCM auth tag
public class AESCryptoModule: Module {
public func definition() -> ModuleDefinition {
Name("AESCrypto")
Function("generateKey", generateKey)
+ Function("encrypt", encrypt)
}
}
@@ -23,9 +26,38 @@
}
}
+private func encrypt(rawKey: Uint8Array,
+ plaintext: Uint8Array,
+ destination: Uint8Array) throws {
+ guard destination.byteLength == plaintext.byteLength + IV_LENGTH + TAG_LENGTH
+ else {
+ throw InvalidDataLengthException()
+ }
+
+ let key = SymmetricKey(data: rawKey.data())
+ let iv = AES.GCM.Nonce()
+ let encryptionResult = try AES.GCM.seal(plaintext.data(),
+ using: key,
+ nonce: iv)
+
+ // 'combined' returns concatenated: iv || ciphertext || tag
+ guard let sealedData = encryptionResult.combined else {
+ // this happens only if Nonce/IV != 12 bytes long
+ throw EncryptionFailedException("Incorrect AES configuration")
+ }
+ guard sealedData.count == destination.byteLength else {
+ throw EncryptionFailedException("Encrypted data has unexpected length")
+ }
+ sealedData.copyBytes(to: destination.rawBufferPtr())
+}
+
// MARK: - Utilities
extension TypedArray {
+ func data() -> Data {
+ Data(bytes: self.rawPointer, count: self.byteLength)
+ }
+
func rawBufferPtr() -> UnsafeMutableRawBufferPointer {
UnsafeMutableRawBufferPointer(start: self.rawPointer,
count: self.byteLength)
@@ -39,3 +71,15 @@
"The AES key has invalid length"
}
}
+
+private class InvalidDataLengthException: Exception {
+ override var reason: String {
+ "Source or destination array has invalid length"
+ }
+}
+
+private class EncryptionFailedException: GenericException<String> {
+ override var reason: String {
+ "Failed to encrypt data: \(param)"
+ }
+}
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,11 +1,19 @@
// @flow
import { requireNativeModule } from 'expo-modules-core';
+import invariant from 'invariant';
const KEY_SIZE = 32; // bytes
+const IV_LENGTH = 12; // bytes, IV - unique Initialization Vector (nonce)
+const TAG_LENGTH = 16; // bytes - GCM auth tag
const AESCryptoModule: {
+generateKey: (destination: Uint8Array) => void,
+ +encrypt: (
+ key: Uint8Array,
+ data: Uint8Array,
+ destination: Uint8Array,
+ ) => void,
} = requireNativeModule('AESCrypto');
export function generateKey(): Uint8Array {
@@ -13,3 +21,10 @@
AESCryptoModule.generateKey(keyBuffer);
return keyBuffer;
}
+
+export function encrypt(key: Uint8Array, data: Uint8Array): Uint8Array {
+ invariant(AESCryptoModule.encrypt, 'AESCrypto.encrypt is not implemented');
+ const sealedDataBuffer = new Uint8Array(data.length + IV_LENGTH + TAG_LENGTH);
+ AESCryptoModule.encrypt(key, data, sealedDataBuffer);
+ return sealedDataBuffer;
+}

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 27, 1:40 AM (9 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2587273
Default Alt Text
D7005.id23841.diff (3 KB)

Event Timeline