diff --git a/native/expo-modules/comm-expo-package/ios/AESCryptoModule.swift b/native/expo-modules/comm-expo-package/ios/AESCryptoModule.swift --- a/native/expo-modules/comm-expo-package/ios/AESCryptoModule.swift +++ b/native/expo-modules/comm-expo-package/ios/AESCryptoModule.swift @@ -15,29 +15,76 @@ } } +@objc(AESCryptoModuleObjCCompat) +public class AESCryptoModuleObjCCompat: NSObject { + + @objc(generateKey:withError:) + public func generateKey(destination: NSMutableData) throws { + let destinationPtr = UnsafeMutableRawBufferPointer(start: destination.mutableBytes, + count: KEY_SIZE) + try! generateKeyCommon(destination: destinationPtr, + byteLength: destination.length) + } + + @objc(encryptWithKey:plaintext:destination:withError:) + public func encrypt(rawKey: Data, + plaintext: Data, + destination: NSMutableData) throws { + let destinationPtr = UnsafeMutableRawBufferPointer(start: destination.mutableBytes, + count: destination.length) + try! encryptCommon(rawKey: rawKey, + plaintext: plaintext, + plaintextLength: plaintext.count, + destination: destinationPtr, + destinationLength: destination.length) + } + + @objc(decryptWithKey:sealedData:destination:withError:) + public func decrypt(rawKey: Data, + sealedData: Data, + destination: NSMutableData) throws { + let destinationPtr = UnsafeMutableRawBufferPointer(start: destination.mutableBytes, + count: destination.length) + try! decryptCommon(rawKey: rawKey, + sealedData: sealedData, + sealedDataLength: sealedData.count, + destination: destinationPtr, + destinationLength: destination.length) + } + +} + // MARK: - Function implementations -private func generateKey(destination: Uint8Array) throws { - guard destination.byteLength == KEY_SIZE else { +private func generateKeyCommon(destination: UnsafeMutableRawBufferPointer, + byteLength: Int) throws { + guard byteLength == KEY_SIZE else { throw InvalidKeyLengthException() } let key = SymmetricKey(size: .bits256) key.withUnsafeBytes { bytes in - let _ = bytes.copyBytes(to: destination.rawBufferPtr()) + let _ = bytes.copyBytes(to: destination) } } -private func encrypt(rawKey: Uint8Array, - plaintext: Uint8Array, - destination: Uint8Array) throws { - guard destination.byteLength == plaintext.byteLength + IV_LENGTH + TAG_LENGTH +private func generateKey(destination: Uint8Array) throws { + try! generateKeyCommon(destination: destination.rawBufferPtr(), + byteLength: destination.byteLength) +} + +private func encryptCommon(rawKey: Data, + plaintext: Data, + plaintextLength: Int, + destination: UnsafeMutableRawBufferPointer, + destinationLength: Int) throws { + guard destinationLength == plaintextLength + IV_LENGTH + TAG_LENGTH else { throw InvalidDataLengthException() } - let key = SymmetricKey(data: rawKey.data()) + let key = SymmetricKey(data: rawKey) let iv = AES.GCM.Nonce() - let encryptionResult = try AES.GCM.seal(plaintext.data(), + let encryptionResult = try AES.GCM.seal(plaintext, using: key, nonce: iv) @@ -46,24 +93,46 @@ // this happens only if Nonce/IV != 12 bytes long throw EncryptionFailedException("Incorrect AES configuration") } - guard sealedData.count == destination.byteLength else { + guard sealedData.count == destinationLength else { throw EncryptionFailedException("Encrypted data has unexpected length") } - sealedData.copyBytes(to: destination.rawBufferPtr()) + sealedData.copyBytes(to: destination) +} + +private func encrypt(rawKey: Uint8Array, + plaintext: Uint8Array, + destination: Uint8Array) throws { + try! encryptCommon(rawKey: rawKey.data(), + plaintext: plaintext.data(), + plaintextLength: plaintext.byteLength, + destination: destination.rawBufferPtr(), + destinationLength: destination.byteLength) +} + +private func decryptCommon(rawKey: Data, + sealedData: Data, + sealedDataLength: Int, + destination: UnsafeMutableRawBufferPointer, + destinationLength: Int) throws { + guard destinationLength == sealedDataLength - IV_LENGTH - TAG_LENGTH + else { + throw InvalidDataLengthException() + } + + let key = SymmetricKey(data: rawKey) + let sealedBox = try AES.GCM.SealedBox(combined: sealedData) + let plaintext = try AES.GCM.open(sealedBox, using: key) + plaintext.copyBytes(to: destination) } 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()) + try! decryptCommon(rawKey: rawKey.data(), + sealedData: sealedData.data(), + sealedDataLength: sealedData.byteLength, + destination: destination.rawBufferPtr(), + destinationLength: destination.byteLength) } // MARK: - Exception definitions diff --git a/native/expo-modules/comm-expo-package/ios/CommExpoPackage.podspec b/native/expo-modules/comm-expo-package/ios/CommExpoPackage.podspec --- a/native/expo-modules/comm-expo-package/ios/CommExpoPackage.podspec +++ b/native/expo-modules/comm-expo-package/ios/CommExpoPackage.podspec @@ -19,9 +19,18 @@ # Swift/Objective-C compatibility s.pod_target_xcconfig = { + 'USE_HEADERMAP' => 'YES', 'DEFINES_MODULE' => 'YES', 'SWIFT_COMPILATION_MODE' => 'wholemodule' } + user_header_search_paths = [ + '"${PODS_CONFIGURATION_BUILD_DIR}/CommExpoPackage/Swift Compatibility Header"', + ] + s.user_target_xcconfig = { + "HEADER_SEARCH_PATHS" => user_header_search_paths, + } + s.source_files = "**/*.{h,m,swift}" + s.public_header_files = '**/*.h' end diff --git a/native/expo-modules/comm-expo-package/ios/CommExpoPackageObjCCompat.h b/native/expo-modules/comm-expo-package/ios/CommExpoPackageObjCCompat.h new file mode 100644 --- /dev/null +++ b/native/expo-modules/comm-expo-package/ios/CommExpoPackageObjCCompat.h @@ -0,0 +1,3 @@ +#if __has_include("CommExpoPackage-Swift.h") +#import "CommExpoPackage-Swift.h" +#endif diff --git a/native/ios/Podfile b/native/ios/Podfile --- a/native/ios/Podfile +++ b/native/ios/Podfile @@ -54,6 +54,7 @@ common_comm_target_pods pod 'OLMKit', :path => "../node_modules/olm" pod 'RCT-Folly', :podspec => "../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" + pod 'CommExpoPackage', :path => "../expo-modules/comm-expo-package/ios" react_native_config end diff --git a/native/ios/Podfile.lock b/native/ios/Podfile.lock --- a/native/ios/Podfile.lock +++ b/native/ios/Podfile.lock @@ -838,7 +838,7 @@ SPEC CHECKSUMS: boost: a7c83b31436843459a1961bfd74b96033dc77234 - CommExpoPackage: 3f9d8a25537fb9d80f79a63fd1e73c51f55b87e9 + CommExpoPackage: 71183609c6fd4263fff6b24bde778f3fb2d035ef DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 DVAssetLoaderDelegate: 0caec20e4e08b8560b691131539e9180024d4bce EXApplication: d8f53a7eee90a870a75656280e8d4b85726ea903 @@ -936,6 +936,6 @@ SQLCipher-Amalgamation: cbd36045fe7b458b8a442958a01aefdbc44c20f8 Yoga: d6133108734e69e8c0becc6ba587294b94829687 -PODFILE CHECKSUM: 60ed9de6b14a66c6022cd82cafcb04594edd7eaf +PODFILE CHECKSUM: b1546433c0563b58e7a664c1e21b4fa8402fd644 COCOAPODS: 1.11.3