Changeset View
Changeset View
Standalone View
Standalone View
native/expo-modules/aes-crypto/ios/AESCryptoModule.swift
import ExpoModulesCore | import ExpoModulesCore | ||||
import CryptoKit | import CryptoKit | ||||
private let KEY_SIZE = 32 // bytes | private let KEY_SIZE = 32 // bytes | ||||
private let IV_LENGTH = 12 // bytes, IV - unique Initialization Vector (nonce) | private let IV_LENGTH = 12 // bytes, IV - unique Initialization Vector (nonce) | ||||
private let TAG_LENGTH = 16 // bytes - GCM auth tag | private let TAG_LENGTH = 16 // bytes - GCM auth tag | ||||
public class AESCryptoModule: Module { | public class AESCryptoModule: Module { | ||||
public func definition() -> ModuleDefinition { | public func definition() -> ModuleDefinition { | ||||
Name("AESCrypto") | Name("AESCrypto") | ||||
Function("generateKey", generateKey) | Function("generateKey", generateKey) | ||||
Function("encrypt", encrypt) | Function("encrypt", encrypt) | ||||
Function("decrypt", decrypt) | |||||
} | } | ||||
} | } | ||||
// MARK: - Function implementations | // MARK: - Function implementations | ||||
private func generateKey(destination: Uint8Array) throws { | private func generateKey(destination: Uint8Array) throws { | ||||
guard destination.byteLength == KEY_SIZE else { | guard destination.byteLength == KEY_SIZE else { | ||||
throw InvalidKeyLengthException() | throw InvalidKeyLengthException() | ||||
Show All 24 Lines | guard let sealedData = encryptionResult.combined else { | ||||
throw EncryptionFailedException("Incorrect AES configuration") | throw EncryptionFailedException("Incorrect AES configuration") | ||||
} | } | ||||
guard sealedData.count == destination.byteLength else { | guard sealedData.count == destination.byteLength else { | ||||
throw EncryptionFailedException("Encrypted data has unexpected length") | throw EncryptionFailedException("Encrypted data has unexpected length") | ||||
} | } | ||||
sealedData.copyBytes(to: destination.rawBufferPtr()) | 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 | // MARK: - Utilities | ||||
extension TypedArray { | extension TypedArray { | ||||
func data() -> Data { | func data() -> Data { | ||||
Data(bytes: self.rawPointer, count: self.byteLength) | Data(bytes: self.rawPointer, count: self.byteLength) | ||||
} | } | ||||
func rawBufferPtr() -> UnsafeMutableRawBufferPointer { | func rawBufferPtr() -> UnsafeMutableRawBufferPointer { | ||||
Show All 24 Lines |