diff --git a/packages/native_crypto_ios/ios/Classes/NativeCrypto.swift b/packages/native_crypto_ios/ios/Classes/NativeCrypto.swift new file mode 100644 index 0000000..ca8fa2c --- /dev/null +++ b/packages/native_crypto_ios/ios/Classes/NativeCrypto.swift @@ -0,0 +1,113 @@ +// +// NativeCrypto.swift +// native_crypto_ios +// +// Created by Hugo Pointcheval on 04/04/2023. +// + +import Foundation +import CryptoKit + +public class NativeCrypto: NSObject, NativeCryptoAPI { + func hash(data: FlutterStandardTypedData, algorithm: HashAlgorithm) throws -> FlutterStandardTypedData? { + var md = HashAlgorithmParser.getMessageDigest(algorithm: algorithm) + md.update(data: data.data) + + let bytes = Data(md.finalize()) + + return FlutterStandardTypedData(bytes: bytes) + } + + func hmac(data: FlutterStandardTypedData, key: FlutterStandardTypedData, algorithm: HashAlgorithm) throws -> FlutterStandardTypedData? { + let symmetricKey : SymmetricKey = SymmetricKey.init(data: key.data) + + switch algorithm { + case .sha256: return FlutterStandardTypedData(bytes: Data(HMAC(key: symmetricKey).finalize())) + case .sha384: return FlutterStandardTypedData(bytes: Data(HMAC(key: symmetricKey).finalize())) + case .sha512: return FlutterStandardTypedData(bytes: Data(HMAC(key: symmetricKey).finalize())) + @unknown default: fatalError("Unknown algorithm") + } + } + + func generateSecureRandom(length: Int64) throws -> FlutterStandardTypedData? { + let lengthInt = Int(truncatingIfNeeded: length) + let symmetricKey = SymmetricKey.init(size: SymmetricKeySize(bitCount: lengthInt / 8)) + let bytes = symmetricKey.withUnsafeBytes + { + return Data(Array($0)) + } + + return FlutterStandardTypedData(bytes: bytes) + } + + func pbkdf2(password: FlutterStandardTypedData, salt: FlutterStandardTypedData, length: Int64, iterations: Int64, algorithm: HashAlgorithm) throws -> FlutterStandardTypedData? { + let lengthInt = Int(truncatingIfNeeded: length) + let iterationsInt = Int(truncatingIfNeeded: iterations) + let pbkdf2 = Pbkdf2(length: lengthInt, iterations: iterationsInt, hashAlgorithm: algorithm) + pbkdf2.initialize(password: password.data, salt: salt.data) + let data = try? pbkdf2.derive() + + if (data == nil) { + return nil + } + + return FlutterStandardTypedData(bytes: data!) + } + + func encrypt(plainText: FlutterStandardTypedData, key: FlutterStandardTypedData, algorithm: CipherAlgorithm) throws -> FlutterStandardTypedData? { + let aes = AESCipher() + let bytes = try? aes.encrypt(data: plainText.data, key: key.data, predefinedIV: nil) + + if (bytes == nil) { + return nil + } + + return FlutterStandardTypedData(bytes: bytes!) + } + + func encryptWithIV(plainText: FlutterStandardTypedData, iv: FlutterStandardTypedData, key: FlutterStandardTypedData, algorithm: CipherAlgorithm) throws -> FlutterStandardTypedData? { + let aes = AESCipher() + let bytes = try? aes.encrypt(data: plainText.data, key: key.data, predefinedIV: iv.data) + + if (bytes == nil) { + return nil + } + + return FlutterStandardTypedData(bytes: bytes!) + } + + func decrypt(cipherText: FlutterStandardTypedData, key: FlutterStandardTypedData, algorithm: CipherAlgorithm) throws -> FlutterStandardTypedData? { + let aes = AESCipher() + let bytes = try? aes.decrypt(data: cipherText.data, key: key.data) + + if (bytes == nil) { + return nil + } + + return FlutterStandardTypedData(bytes: bytes!) + } + + func encryptFile(plainTextPath: String, cipherTextPath: String, key: FlutterStandardTypedData, algorithm: CipherAlgorithm) throws -> Bool? { + let aes = AESCipher() + let params = FileParameters(input: plainTextPath, output: cipherTextPath) + let success = try? aes.encryptFile(fileParameters: params, key: key.data, predefinedIV: nil) + + return success + } + + func encryptFileWithIV(plainTextPath: String, cipherTextPath: String, iv: FlutterStandardTypedData, key: FlutterStandardTypedData, algorithm: CipherAlgorithm) throws -> Bool? { + let aes = AESCipher() + let params = FileParameters(input: plainTextPath, output: cipherTextPath) + let success = try? aes.encryptFile(fileParameters: params, key: key.data, predefinedIV: iv.data) + + return success + } + + func decryptFile(cipherTextPath: String, plainTextPath: String, key: FlutterStandardTypedData, algorithm: CipherAlgorithm) throws -> Bool? { + let aes = AESCipher() + let params = FileParameters(input: cipherTextPath, output: plainTextPath) + let success = try? aes.decryptFile(fileParameters: params, key: key.data) + + return success + } +} diff --git a/packages/native_crypto_ios/ios/Classes/Public/messages.g.h b/packages/native_crypto_ios/ios/Classes/Public/messages.g.h deleted file mode 100644 index 6caeca0..0000000 --- a/packages/native_crypto_ios/ios/Classes/Public/messages.g.h +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2019-2023 Hugo Pointcheval -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file or at -// https://opensource.org/licenses/MIT. -// -- -// Autogenerated from Pigeon (v9.0.0), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -#import - -@protocol FlutterBinaryMessenger; -@protocol FlutterMessageCodec; -@class FlutterError; -@class FlutterStandardTypedData; - -NS_ASSUME_NONNULL_BEGIN - -@class HashRequest; -@class HashResponse; -@class HmacRequest; -@class HmacResponse; -@class GenerateSecureRandomRequest; -@class GenerateSecureRandomResponse; -@class Pbkdf2Request; -@class Pbkdf2Response; -@class EncryptRequest; -@class EncryptResponse; -@class DecryptRequest; -@class DecryptResponse; -@class EncryptFileRequest; -@class EncryptFileResponse; -@class DecryptFileRequest; -@class DecryptFileResponse; -@class EncryptWithIVRequest; - -@interface HashRequest : NSObject -+ (instancetype)makeWithData:(nullable FlutterStandardTypedData *)data - algorithm:(nullable NSString *)algorithm; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * data; -@property(nonatomic, copy, nullable) NSString * algorithm; -@end - -@interface HashResponse : NSObject -+ (instancetype)makeWithHash:(nullable FlutterStandardTypedData *)hash; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * hash; -@end - -@interface HmacRequest : NSObject -+ (instancetype)makeWithData:(nullable FlutterStandardTypedData *)data - key:(nullable FlutterStandardTypedData *)key - algorithm:(nullable NSString *)algorithm; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * data; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * key; -@property(nonatomic, copy, nullable) NSString * algorithm; -@end - -@interface HmacResponse : NSObject -+ (instancetype)makeWithHmac:(nullable FlutterStandardTypedData *)hmac; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * hmac; -@end - -@interface GenerateSecureRandomRequest : NSObject -+ (instancetype)makeWithLength:(nullable NSNumber *)length; -@property(nonatomic, strong, nullable) NSNumber * length; -@end - -@interface GenerateSecureRandomResponse : NSObject -+ (instancetype)makeWithRandom:(nullable FlutterStandardTypedData *)random; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * random; -@end - -@interface Pbkdf2Request : NSObject -+ (instancetype)makeWithPassword:(nullable FlutterStandardTypedData *)password - salt:(nullable FlutterStandardTypedData *)salt - length:(nullable NSNumber *)length - iterations:(nullable NSNumber *)iterations - hashAlgorithm:(nullable NSString *)hashAlgorithm; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * password; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * salt; -@property(nonatomic, strong, nullable) NSNumber * length; -@property(nonatomic, strong, nullable) NSNumber * iterations; -@property(nonatomic, copy, nullable) NSString * hashAlgorithm; -@end - -@interface Pbkdf2Response : NSObject -+ (instancetype)makeWithKey:(nullable FlutterStandardTypedData *)key; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * key; -@end - -@interface EncryptRequest : NSObject -+ (instancetype)makeWithPlainText:(nullable FlutterStandardTypedData *)plainText - key:(nullable FlutterStandardTypedData *)key - algorithm:(nullable NSString *)algorithm; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * plainText; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * key; -@property(nonatomic, copy, nullable) NSString * algorithm; -@end - -@interface EncryptResponse : NSObject -+ (instancetype)makeWithCipherText:(nullable FlutterStandardTypedData *)cipherText; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * cipherText; -@end - -@interface DecryptRequest : NSObject -+ (instancetype)makeWithCipherText:(nullable FlutterStandardTypedData *)cipherText - key:(nullable FlutterStandardTypedData *)key - algorithm:(nullable NSString *)algorithm; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * cipherText; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * key; -@property(nonatomic, copy, nullable) NSString * algorithm; -@end - -@interface DecryptResponse : NSObject -+ (instancetype)makeWithPlainText:(nullable FlutterStandardTypedData *)plainText; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * plainText; -@end - -@interface EncryptFileRequest : NSObject -+ (instancetype)makeWithPlainTextPath:(nullable NSString *)plainTextPath - cipherTextPath:(nullable NSString *)cipherTextPath - key:(nullable FlutterStandardTypedData *)key - algorithm:(nullable NSString *)algorithm; -@property(nonatomic, copy, nullable) NSString * plainTextPath; -@property(nonatomic, copy, nullable) NSString * cipherTextPath; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * key; -@property(nonatomic, copy, nullable) NSString * algorithm; -@end - -@interface EncryptFileResponse : NSObject -+ (instancetype)makeWithSuccess:(nullable NSNumber *)success; -@property(nonatomic, strong, nullable) NSNumber * success; -@end - -@interface DecryptFileRequest : NSObject -+ (instancetype)makeWithCipherTextPath:(nullable NSString *)cipherTextPath - plainTextPath:(nullable NSString *)plainTextPath - key:(nullable FlutterStandardTypedData *)key - algorithm:(nullable NSString *)algorithm; -@property(nonatomic, copy, nullable) NSString * cipherTextPath; -@property(nonatomic, copy, nullable) NSString * plainTextPath; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * key; -@property(nonatomic, copy, nullable) NSString * algorithm; -@end - -@interface DecryptFileResponse : NSObject -+ (instancetype)makeWithSuccess:(nullable NSNumber *)success; -@property(nonatomic, strong, nullable) NSNumber * success; -@end - -@interface EncryptWithIVRequest : NSObject -+ (instancetype)makeWithPlainText:(nullable FlutterStandardTypedData *)plainText - iv:(nullable FlutterStandardTypedData *)iv - key:(nullable FlutterStandardTypedData *)key - algorithm:(nullable NSString *)algorithm; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * plainText; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * iv; -@property(nonatomic, strong, nullable) FlutterStandardTypedData * key; -@property(nonatomic, copy, nullable) NSString * algorithm; -@end - -/// The codec used by NativeCryptoAPI. -NSObject *NativeCryptoAPIGetCodec(void); - -@protocol NativeCryptoAPI -/// @return `nil` only when `error != nil`. -- (nullable HashResponse *)hashRequest:(HashRequest *)request error:(FlutterError *_Nullable *_Nonnull)error; -/// @return `nil` only when `error != nil`. -- (nullable HmacResponse *)hmacRequest:(HmacRequest *)request error:(FlutterError *_Nullable *_Nonnull)error; -/// @return `nil` only when `error != nil`. -- (nullable GenerateSecureRandomResponse *)generateSecureRandomRequest:(GenerateSecureRandomRequest *)request error:(FlutterError *_Nullable *_Nonnull)error; -/// @return `nil` only when `error != nil`. -- (nullable Pbkdf2Response *)pbkdf2Request:(Pbkdf2Request *)request error:(FlutterError *_Nullable *_Nonnull)error; -/// @return `nil` only when `error != nil`. -- (nullable EncryptResponse *)encryptRequest:(EncryptRequest *)request error:(FlutterError *_Nullable *_Nonnull)error; -/// @return `nil` only when `error != nil`. -- (nullable DecryptResponse *)decryptRequest:(DecryptRequest *)request error:(FlutterError *_Nullable *_Nonnull)error; -/// @return `nil` only when `error != nil`. -- (nullable EncryptFileResponse *)encryptFileRequest:(EncryptFileRequest *)request error:(FlutterError *_Nullable *_Nonnull)error; -/// @return `nil` only when `error != nil`. -- (nullable DecryptFileResponse *)decryptFileRequest:(DecryptFileRequest *)request error:(FlutterError *_Nullable *_Nonnull)error; -/// @return `nil` only when `error != nil`. -- (nullable EncryptResponse *)encryptWithIVRequest:(EncryptWithIVRequest *)request error:(FlutterError *_Nullable *_Nonnull)error; -@end - -extern void NativeCryptoAPISetup(id binaryMessenger, NSObject *_Nullable api); - -NS_ASSUME_NONNULL_END diff --git a/packages/native_crypto_ios/ios/Classes/SwiftNativeCryptoIosPlugin.swift b/packages/native_crypto_ios/ios/Classes/SwiftNativeCryptoIosPlugin.swift index c9b1a84..8a6a342 100644 --- a/packages/native_crypto_ios/ios/Classes/SwiftNativeCryptoIosPlugin.swift +++ b/packages/native_crypto_ios/ios/Classes/SwiftNativeCryptoIosPlugin.swift @@ -3,144 +3,9 @@ import UIKit @available(iOS 13.0, *) public class SwiftNativeCryptoIosPlugin: NSObject, FlutterPlugin { - static let name: String = "plugins.hugop.cl/native_crypto" - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: name, binaryMessenger: registrar.messenger()) - let instance = SwiftNativeCryptoIosPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) + let messenger : FlutterBinaryMessenger = registrar.messenger() + let api : NativeCryptoAPI & NSObjectProtocol = NativeCrypto.init() + NativeCryptoAPISetup.setUp(binaryMessenger: messenger, api: api); } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - switch call.method { - case "digest": _call(task: handleDigest(call: call), result: result) - case "generateSecretKey": _call(task: handleGenerateSecretKey(call: call), result: result) - case "pbkdf2": _call(task: handlePbkdf2(call: call), result: result) - case "encryptAsList": _call(task: handleEncryptAsList(call: call), result: result) - case "decryptAsList": _call(task: handleDecryptAsList(call: call), result: result) - case "encrypt": _call(task: handleCrypt(call: call, forEncryption: true), result: result) - case "decrypt": _call(task: handleCrypt(call: call, forEncryption: false), result: result) - default: result(FlutterMethodNotImplemented) - } - } - - private func _call(task: Task, result: @escaping FlutterResult) { - task.call() - task.finalize(callback: {(task: Task) in - if (task.isSuccessful()) { - result(task.getResult()!) - } else { - let exception: Error = task.getException() - let message = exception.localizedDescription - result(FlutterError(code: "native_crypto", message: message, details: nil)) - } - }) - } - - private func handleDigest(call: FlutterMethodCall) -> Task { - return Task(task: { - let args : NSDictionary = call.arguments as! NSDictionary - - let data : Data = (args["data"] as! FlutterStandardTypedData).data - let algorithm : String = args["algorithm"] as! String - - return FlutterStandardTypedData.init(bytes: try HashAlgorithm.digest(data: data, algorithm: algorithm)) - }) - } - - private func handleGenerateSecretKey(call: FlutterMethodCall) -> Task { - return Task(task: { - let args : NSDictionary = call.arguments as! NSDictionary - - let bitsCount : NSNumber = args["bitsCount"] as! NSNumber - - return FlutterStandardTypedData.init(bytes: SecretKey(fromSecureRandom: bitsCount.intValue).bytes) - }) - } - - private func handlePbkdf2(call: FlutterMethodCall) -> Task { - return Task(task: { - let args : NSDictionary = call.arguments as! NSDictionary - - let password : String = args["password"] as! String - let salt : String = args["salt"] as! String - let keyBytesCount : NSNumber = args["keyBytesCount"] as! NSNumber - let iterations : NSNumber = args["iterations"] as! NSNumber - let algorithm : String = args["algorithm"] as! String - - let pbkdf2 : Pbkdf2 = Pbkdf2(keyBytesCount: keyBytesCount.intValue, iterations: iterations.intValue) - pbkdf2.hash = HashAlgorithm.init(rawValue: algorithm) ?? pbkdf2.hash - pbkdf2.initialize(password: password, salt: salt) - - return FlutterStandardTypedData.init(bytes: try pbkdf2.derive().bytes) - }) - } - - private func handleEncryptAsList(call: FlutterMethodCall) -> Task> { - return Task(task: { - let args : NSDictionary = call.arguments as! NSDictionary - - let data : Data = (args["data"] as! FlutterStandardTypedData).data - let key : Data = (args["key"] as! FlutterStandardTypedData).data - let algorithm : String = args["algorithm"] as! String - - let cipherAlgorithm : CipherAlgorithm? = CipherAlgorithm.init(rawValue: algorithm) - var cipher : Cipher - if (cipherAlgorithm != nil) { - cipher = cipherAlgorithm!.getCipher - } else { - throw NativeCryptoError.cipherError - } - - return try cipher.encryptAsList(data: data, key: key) - }) - } - - private func handleDecryptAsList(call: FlutterMethodCall) -> Task { - return Task(task: { - let args : NSDictionary = call.arguments as! NSDictionary - - let data = args["data"] as! NSArray - let key : Data = (args["key"] as! FlutterStandardTypedData).data - let algorithm : String = args["algorithm"] as! String - - let iv = (data[0] as! FlutterStandardTypedData).data - let encrypted = (data[1] as! FlutterStandardTypedData).data - - let cipherAlgorithm : CipherAlgorithm? = CipherAlgorithm.init(rawValue: algorithm) - var cipher : Cipher - if (cipherAlgorithm != nil) { - cipher = cipherAlgorithm!.getCipher - } else { - throw NativeCryptoError.cipherError - } - - return FlutterStandardTypedData.init(bytes: try cipher.decryptAsList(data: [iv, encrypted], key: key)) - }) - } - - private func handleCrypt(call: FlutterMethodCall, forEncryption: Bool) -> Task { - return Task(task: { - let args : NSDictionary = call.arguments as! NSDictionary - - let data : Data = (args["data"] as! FlutterStandardTypedData).data - let key : Data = (args["key"] as! FlutterStandardTypedData).data - let algorithm : String = args["algorithm"] as! String - - let cipherAlgorithm : CipherAlgorithm? = CipherAlgorithm.init(rawValue: algorithm) - var cipher : Cipher - if (cipherAlgorithm != nil) { - cipher = cipherAlgorithm!.getCipher - } else { - throw NativeCryptoError.cipherError - } - - if (forEncryption) { - return FlutterStandardTypedData.init(bytes: try cipher.encrypt(data: data, key: key)) - } else { - return FlutterStandardTypedData.init(bytes: try cipher.decrypt(data: data, key: key)) - } - }) - } - } diff --git a/packages/native_crypto_ios/ios/Classes/ciphers/AESCipher.swift b/packages/native_crypto_ios/ios/Classes/ciphers/AESCipher.swift index 2110ff5..20c48ff 100644 --- a/packages/native_crypto_ios/ios/Classes/ciphers/AESCipher.swift +++ b/packages/native_crypto_ios/ios/Classes/ciphers/AESCipher.swift @@ -9,17 +9,33 @@ import Foundation import CryptoKit class AESCipher : Cipher { - var algorithm: CipherAlgorithm = CipherAlgorithm.aes - /// Encrypts plaintext with key using AES GCM @available(iOS 13.0, *) - func encrypt(data: Data, key: Data) throws -> Data { + func encrypt(data: Data, key: Data, predefinedIV: Data?) throws -> Data { let symmetricKey : SymmetricKey = SymmetricKey.init(data: key) - let encrypted : AES.GCM.SealedBox? = try? AES.GCM.seal(data, using: symmetricKey) - let encryptedData : Data? = encrypted?.combined + // Encryption + var encrypted : AES.GCM.SealedBox + do { + // If predefinedIV is not null use it + if (predefinedIV != nil) { + let nonce = try AES.GCM.Nonce(data: predefinedIV!) + encrypted = try AES.GCM.seal(data, using: symmetricKey, nonce: nonce) + } else { + encrypted = try AES.GCM.seal(data, using: symmetricKey) + } + } catch CryptoKitError.incorrectKeySize { + throw NativeCryptoError.invalidKeySize() + } catch CryptoKitError.invalidParameter, CryptoKitError.incorrectParameterSize { + throw NativeCryptoError.invalidParameter() + } catch { + throw NativeCryptoError.unknownError(reason: "An error occured during encryption.") + } + + // NONCE[12] || CIPHERTEXT[n] || TAG[16] + let encryptedData : Data? = encrypted.combined if (encryptedData == nil) { - throw NativeCryptoError.encryptionError + throw NativeCryptoError.unknownError(reason: "An error occured during ciphertext combination.") } return encryptedData! } @@ -28,30 +44,65 @@ class AESCipher : Cipher { @available(iOS 13.0, *) func decrypt(data: Data, key: Data) throws -> Data { let symmetricKey = SymmetricKey.init(data: key) - let sealedBox = try? AES.GCM.SealedBox(combined: data) - if (sealedBox == nil) { return Data.init() } - let decryptedData = try? AES.GCM.open(sealedBox!, using: symmetricKey) - if (decryptedData == nil) { - throw NativeCryptoError.decryptionError + + // SealedBox initialization + var encrypted : AES.GCM.SealedBox + do { + encrypted = try AES.GCM.SealedBox(combined: data) + } catch { + throw NativeCryptoError.unknownError(reason: "An error occured during sealedbox initialization.") } - return decryptedData! - } - - func encryptAsList(data: Data, key: Data) throws -> [Data] { - let encryptedData = try encrypt(data: data, key: key) - let iv = encryptedData.prefix(12) - let data = encryptedData.suffix(from: 12) + // Decryption + var decryptedData : Data + do { + decryptedData = try AES.GCM.open(encrypted, using: symmetricKey) + } catch CryptoKitError.incorrectKeySize { + throw NativeCryptoError.invalidKeySize() + } catch CryptoKitError.invalidParameter, CryptoKitError.incorrectParameterSize { + throw NativeCryptoError.invalidParameter() + } catch CryptoKitError.authenticationFailure { + throw NativeCryptoError.authenticationError() + } catch { + throw NativeCryptoError.unknownError(reason: "An error occured during decryption.") + } - return [iv, data] - } - - func decryptAsList(data: [Data], key: Data) throws -> Data { - var encryptedData = data.first! - let data = data.last! - encryptedData.append(data) - - let decryptedData = try decrypt(data: encryptedData, key: key) return decryptedData } + + /// Encrypts plaintext file with key using AES GCM + func encryptFile(fileParameters: FileParameters, key: Data, predefinedIV: Data?) throws -> Bool { + let fileManager = FileManager.default + let inputFile = URL(fileURLWithPath: fileParameters.inputPath) + + guard let data = fileManager.contents(atPath: inputFile.path) else { + throw NativeCryptoError.ioError(reason: "Error while reading input file.") + } + + let encryptedData = try encrypt(data: data, key: key, predefinedIV: predefinedIV) + + guard fileManager.createFile(atPath: fileParameters.outputPath, contents: encryptedData, attributes: nil) else { + throw NativeCryptoError.ioError(reason: "Error while writing output file.") + } + + return true + } + + /// Decrypts ciphertext file with key using AES GCM + func decryptFile(fileParameters: FileParameters, key: Data) throws -> Bool { + let fileManager = FileManager.default + let inputFile = URL(fileURLWithPath: fileParameters.inputPath) + + guard let data = fileManager.contents(atPath: inputFile.path) else { + throw NativeCryptoError.ioError(reason: "Error while reading input file.") + } + + let decryptedData = try decrypt(data: data, key: key) + + guard fileManager.createFile(atPath: fileParameters.outputPath, contents: decryptedData, attributes: nil) else { + throw NativeCryptoError.ioError(reason: "Error while writing output file.") + } + + return true + } } diff --git a/packages/native_crypto_ios/ios/Classes/kdf/Pbkdf2.swift b/packages/native_crypto_ios/ios/Classes/kdf/Pbkdf2.swift index 8a34a1e..0377904 100644 --- a/packages/native_crypto_ios/ios/Classes/kdf/Pbkdf2.swift +++ b/packages/native_crypto_ios/ios/Classes/kdf/Pbkdf2.swift @@ -9,45 +9,42 @@ import Foundation import CommonCrypto class Pbkdf2 : KeyDerivation { - var algorithm: KdfAlgorithm = KdfAlgorithm.pbkdf2 - - var keyBytesCount: Int + var length: Int var iterations: Int - var hash: HashAlgorithm = HashAlgorithm.HashSHA256 + var hashAlgorithm: HashAlgorithm - var password: String? = nil - var salt: String? = nil + var password: Data? = nil + var salt: Data? = nil - init(keyBytesCount: Int, iterations: Int) { - self.keyBytesCount = keyBytesCount + init(length: Int, iterations: Int, hashAlgorithm: HashAlgorithm) { + self.length = length self.iterations = iterations + self.hashAlgorithm = hashAlgorithm } - func initialize(password: String, salt: String) { + func initialize(password: Data, salt: Data) { self.password = password self.salt = salt } - func derive() throws -> SecretKey { + func derive() throws -> Data? { if (password == nil || salt == nil) { - throw NativeCryptoError.pbkdf2Error + throw NativeCryptoError.kdfError(reason: "Password and salt cannot be null.") } - let passwordData = password!.data(using: .utf8)! - let saltData = salt!.data(using: .utf8)! - - var derivedKeyData = Data(repeating: 0, count: keyBytesCount) + var derivedKeyData = Data(repeating: 0, count: length) let localDerivedKeyData = derivedKeyData + let identifier = HashAlgorithmParser.getPbkdf2Identifier(algorithm: hashAlgorithm) let status = derivedKeyData.withUnsafeMutableBytes { (derivedKeyBytes: UnsafeMutableRawBufferPointer) in - saltData.withUnsafeBytes { (saltBytes: UnsafeRawBufferPointer) in + salt!.withUnsafeBytes { (saltBytes: UnsafeRawBufferPointer) in CCKeyDerivationPBKDF( CCPBKDFAlgorithm(kCCPBKDF2), - password, - passwordData.count, + (password! as NSData).bytes, + password!.count, saltBytes.bindMemory(to: UInt8.self).baseAddress, - saltData.count, - hash.pbkdf2identifier, + salt!.count, + identifier, UInt32(iterations), derivedKeyBytes.bindMemory(to: UInt8.self).baseAddress, localDerivedKeyData.count) @@ -55,9 +52,9 @@ class Pbkdf2 : KeyDerivation { } if (status != kCCSuccess) { - throw NativeCryptoError.pbkdf2Error + throw NativeCryptoError.kdfError() } - return SecretKey(derivedKeyData) + return derivedKeyData } } diff --git a/packages/native_crypto_ios/ios/Classes/keys/SecretKey.swift b/packages/native_crypto_ios/ios/Classes/keys/SecretKey.swift deleted file mode 100644 index 6325143..0000000 --- a/packages/native_crypto_ios/ios/Classes/keys/SecretKey.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// SecretKey.swift -// native_crypto_ios -// -// Created by Hugo Pointcheval on 25/05/2022. -// - -import Foundation -import CryptoKit - -class SecretKey : Key { - var bytes: Data - - init(_ bytes: Data) { - self.bytes = bytes - } - - init(fromSecureRandom bitsCount: Int) { - let symmetricKey = SymmetricKey.init(size: SymmetricKeySize(bitCount: bitsCount)) - bytes = symmetricKey.withUnsafeBytes - { - return Data(Array($0)) - } - } -} diff --git a/packages/native_crypto_ios/ios/Classes/messages.g.m b/packages/native_crypto_ios/ios/Classes/messages.g.m deleted file mode 100644 index 75ff6c3..0000000 --- a/packages/native_crypto_ios/ios/Classes/messages.g.m +++ /dev/null @@ -1,868 +0,0 @@ -// Copyright 2019-2023 Hugo Pointcheval -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file or at -// https://opensource.org/licenses/MIT. -// -- -// Autogenerated from Pigeon (v9.0.0), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -#import "messages.g.h" -#import - -#if !__has_feature(objc_arc) -#error File requires ARC to be enabled. -#endif - -static NSArray *wrapResult(id result, FlutterError *error) { - if (error) { - return @[ - error.code ?: [NSNull null], error.message ?: [NSNull null], error.details ?: [NSNull null] - ]; - } - return @[ result ?: [NSNull null] ]; -} -static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { - id result = array[key]; - return (result == [NSNull null]) ? nil : result; -} - -@interface HashRequest () -+ (HashRequest *)fromList:(NSArray *)list; -+ (nullable HashRequest *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface HashResponse () -+ (HashResponse *)fromList:(NSArray *)list; -+ (nullable HashResponse *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface HmacRequest () -+ (HmacRequest *)fromList:(NSArray *)list; -+ (nullable HmacRequest *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface HmacResponse () -+ (HmacResponse *)fromList:(NSArray *)list; -+ (nullable HmacResponse *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface GenerateSecureRandomRequest () -+ (GenerateSecureRandomRequest *)fromList:(NSArray *)list; -+ (nullable GenerateSecureRandomRequest *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface GenerateSecureRandomResponse () -+ (GenerateSecureRandomResponse *)fromList:(NSArray *)list; -+ (nullable GenerateSecureRandomResponse *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface Pbkdf2Request () -+ (Pbkdf2Request *)fromList:(NSArray *)list; -+ (nullable Pbkdf2Request *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface Pbkdf2Response () -+ (Pbkdf2Response *)fromList:(NSArray *)list; -+ (nullable Pbkdf2Response *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface EncryptRequest () -+ (EncryptRequest *)fromList:(NSArray *)list; -+ (nullable EncryptRequest *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface EncryptResponse () -+ (EncryptResponse *)fromList:(NSArray *)list; -+ (nullable EncryptResponse *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface DecryptRequest () -+ (DecryptRequest *)fromList:(NSArray *)list; -+ (nullable DecryptRequest *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface DecryptResponse () -+ (DecryptResponse *)fromList:(NSArray *)list; -+ (nullable DecryptResponse *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface EncryptFileRequest () -+ (EncryptFileRequest *)fromList:(NSArray *)list; -+ (nullable EncryptFileRequest *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface EncryptFileResponse () -+ (EncryptFileResponse *)fromList:(NSArray *)list; -+ (nullable EncryptFileResponse *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface DecryptFileRequest () -+ (DecryptFileRequest *)fromList:(NSArray *)list; -+ (nullable DecryptFileRequest *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface DecryptFileResponse () -+ (DecryptFileResponse *)fromList:(NSArray *)list; -+ (nullable DecryptFileResponse *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@interface EncryptWithIVRequest () -+ (EncryptWithIVRequest *)fromList:(NSArray *)list; -+ (nullable EncryptWithIVRequest *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; -@end - -@implementation HashRequest -+ (instancetype)makeWithData:(nullable FlutterStandardTypedData *)data - algorithm:(nullable NSString *)algorithm { - HashRequest* pigeonResult = [[HashRequest alloc] init]; - pigeonResult.data = data; - pigeonResult.algorithm = algorithm; - return pigeonResult; -} -+ (HashRequest *)fromList:(NSArray *)list { - HashRequest *pigeonResult = [[HashRequest alloc] init]; - pigeonResult.data = GetNullableObjectAtIndex(list, 0); - pigeonResult.algorithm = GetNullableObjectAtIndex(list, 1); - return pigeonResult; -} -+ (nullable HashRequest *)nullableFromList:(NSArray *)list { - return (list) ? [HashRequest fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.data ?: [NSNull null]), - (self.algorithm ?: [NSNull null]), - ]; -} -@end - -@implementation HashResponse -+ (instancetype)makeWithHash:(nullable FlutterStandardTypedData *)hash { - HashResponse* pigeonResult = [[HashResponse alloc] init]; - pigeonResult.hash = hash; - return pigeonResult; -} -+ (HashResponse *)fromList:(NSArray *)list { - HashResponse *pigeonResult = [[HashResponse alloc] init]; - pigeonResult.hash = GetNullableObjectAtIndex(list, 0); - return pigeonResult; -} -+ (nullable HashResponse *)nullableFromList:(NSArray *)list { - return (list) ? [HashResponse fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.hash ?: [NSNull null]), - ]; -} -@end - -@implementation HmacRequest -+ (instancetype)makeWithData:(nullable FlutterStandardTypedData *)data - key:(nullable FlutterStandardTypedData *)key - algorithm:(nullable NSString *)algorithm { - HmacRequest* pigeonResult = [[HmacRequest alloc] init]; - pigeonResult.data = data; - pigeonResult.key = key; - pigeonResult.algorithm = algorithm; - return pigeonResult; -} -+ (HmacRequest *)fromList:(NSArray *)list { - HmacRequest *pigeonResult = [[HmacRequest alloc] init]; - pigeonResult.data = GetNullableObjectAtIndex(list, 0); - pigeonResult.key = GetNullableObjectAtIndex(list, 1); - pigeonResult.algorithm = GetNullableObjectAtIndex(list, 2); - return pigeonResult; -} -+ (nullable HmacRequest *)nullableFromList:(NSArray *)list { - return (list) ? [HmacRequest fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.data ?: [NSNull null]), - (self.key ?: [NSNull null]), - (self.algorithm ?: [NSNull null]), - ]; -} -@end - -@implementation HmacResponse -+ (instancetype)makeWithHmac:(nullable FlutterStandardTypedData *)hmac { - HmacResponse* pigeonResult = [[HmacResponse alloc] init]; - pigeonResult.hmac = hmac; - return pigeonResult; -} -+ (HmacResponse *)fromList:(NSArray *)list { - HmacResponse *pigeonResult = [[HmacResponse alloc] init]; - pigeonResult.hmac = GetNullableObjectAtIndex(list, 0); - return pigeonResult; -} -+ (nullable HmacResponse *)nullableFromList:(NSArray *)list { - return (list) ? [HmacResponse fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.hmac ?: [NSNull null]), - ]; -} -@end - -@implementation GenerateSecureRandomRequest -+ (instancetype)makeWithLength:(nullable NSNumber *)length { - GenerateSecureRandomRequest* pigeonResult = [[GenerateSecureRandomRequest alloc] init]; - pigeonResult.length = length; - return pigeonResult; -} -+ (GenerateSecureRandomRequest *)fromList:(NSArray *)list { - GenerateSecureRandomRequest *pigeonResult = [[GenerateSecureRandomRequest alloc] init]; - pigeonResult.length = GetNullableObjectAtIndex(list, 0); - return pigeonResult; -} -+ (nullable GenerateSecureRandomRequest *)nullableFromList:(NSArray *)list { - return (list) ? [GenerateSecureRandomRequest fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.length ?: [NSNull null]), - ]; -} -@end - -@implementation GenerateSecureRandomResponse -+ (instancetype)makeWithRandom:(nullable FlutterStandardTypedData *)random { - GenerateSecureRandomResponse* pigeonResult = [[GenerateSecureRandomResponse alloc] init]; - pigeonResult.random = random; - return pigeonResult; -} -+ (GenerateSecureRandomResponse *)fromList:(NSArray *)list { - GenerateSecureRandomResponse *pigeonResult = [[GenerateSecureRandomResponse alloc] init]; - pigeonResult.random = GetNullableObjectAtIndex(list, 0); - return pigeonResult; -} -+ (nullable GenerateSecureRandomResponse *)nullableFromList:(NSArray *)list { - return (list) ? [GenerateSecureRandomResponse fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.random ?: [NSNull null]), - ]; -} -@end - -@implementation Pbkdf2Request -+ (instancetype)makeWithPassword:(nullable FlutterStandardTypedData *)password - salt:(nullable FlutterStandardTypedData *)salt - length:(nullable NSNumber *)length - iterations:(nullable NSNumber *)iterations - hashAlgorithm:(nullable NSString *)hashAlgorithm { - Pbkdf2Request* pigeonResult = [[Pbkdf2Request alloc] init]; - pigeonResult.password = password; - pigeonResult.salt = salt; - pigeonResult.length = length; - pigeonResult.iterations = iterations; - pigeonResult.hashAlgorithm = hashAlgorithm; - return pigeonResult; -} -+ (Pbkdf2Request *)fromList:(NSArray *)list { - Pbkdf2Request *pigeonResult = [[Pbkdf2Request alloc] init]; - pigeonResult.password = GetNullableObjectAtIndex(list, 0); - pigeonResult.salt = GetNullableObjectAtIndex(list, 1); - pigeonResult.length = GetNullableObjectAtIndex(list, 2); - pigeonResult.iterations = GetNullableObjectAtIndex(list, 3); - pigeonResult.hashAlgorithm = GetNullableObjectAtIndex(list, 4); - return pigeonResult; -} -+ (nullable Pbkdf2Request *)nullableFromList:(NSArray *)list { - return (list) ? [Pbkdf2Request fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.password ?: [NSNull null]), - (self.salt ?: [NSNull null]), - (self.length ?: [NSNull null]), - (self.iterations ?: [NSNull null]), - (self.hashAlgorithm ?: [NSNull null]), - ]; -} -@end - -@implementation Pbkdf2Response -+ (instancetype)makeWithKey:(nullable FlutterStandardTypedData *)key { - Pbkdf2Response* pigeonResult = [[Pbkdf2Response alloc] init]; - pigeonResult.key = key; - return pigeonResult; -} -+ (Pbkdf2Response *)fromList:(NSArray *)list { - Pbkdf2Response *pigeonResult = [[Pbkdf2Response alloc] init]; - pigeonResult.key = GetNullableObjectAtIndex(list, 0); - return pigeonResult; -} -+ (nullable Pbkdf2Response *)nullableFromList:(NSArray *)list { - return (list) ? [Pbkdf2Response fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.key ?: [NSNull null]), - ]; -} -@end - -@implementation EncryptRequest -+ (instancetype)makeWithPlainText:(nullable FlutterStandardTypedData *)plainText - key:(nullable FlutterStandardTypedData *)key - algorithm:(nullable NSString *)algorithm { - EncryptRequest* pigeonResult = [[EncryptRequest alloc] init]; - pigeonResult.plainText = plainText; - pigeonResult.key = key; - pigeonResult.algorithm = algorithm; - return pigeonResult; -} -+ (EncryptRequest *)fromList:(NSArray *)list { - EncryptRequest *pigeonResult = [[EncryptRequest alloc] init]; - pigeonResult.plainText = GetNullableObjectAtIndex(list, 0); - pigeonResult.key = GetNullableObjectAtIndex(list, 1); - pigeonResult.algorithm = GetNullableObjectAtIndex(list, 2); - return pigeonResult; -} -+ (nullable EncryptRequest *)nullableFromList:(NSArray *)list { - return (list) ? [EncryptRequest fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.plainText ?: [NSNull null]), - (self.key ?: [NSNull null]), - (self.algorithm ?: [NSNull null]), - ]; -} -@end - -@implementation EncryptResponse -+ (instancetype)makeWithCipherText:(nullable FlutterStandardTypedData *)cipherText { - EncryptResponse* pigeonResult = [[EncryptResponse alloc] init]; - pigeonResult.cipherText = cipherText; - return pigeonResult; -} -+ (EncryptResponse *)fromList:(NSArray *)list { - EncryptResponse *pigeonResult = [[EncryptResponse alloc] init]; - pigeonResult.cipherText = GetNullableObjectAtIndex(list, 0); - return pigeonResult; -} -+ (nullable EncryptResponse *)nullableFromList:(NSArray *)list { - return (list) ? [EncryptResponse fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.cipherText ?: [NSNull null]), - ]; -} -@end - -@implementation DecryptRequest -+ (instancetype)makeWithCipherText:(nullable FlutterStandardTypedData *)cipherText - key:(nullable FlutterStandardTypedData *)key - algorithm:(nullable NSString *)algorithm { - DecryptRequest* pigeonResult = [[DecryptRequest alloc] init]; - pigeonResult.cipherText = cipherText; - pigeonResult.key = key; - pigeonResult.algorithm = algorithm; - return pigeonResult; -} -+ (DecryptRequest *)fromList:(NSArray *)list { - DecryptRequest *pigeonResult = [[DecryptRequest alloc] init]; - pigeonResult.cipherText = GetNullableObjectAtIndex(list, 0); - pigeonResult.key = GetNullableObjectAtIndex(list, 1); - pigeonResult.algorithm = GetNullableObjectAtIndex(list, 2); - return pigeonResult; -} -+ (nullable DecryptRequest *)nullableFromList:(NSArray *)list { - return (list) ? [DecryptRequest fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.cipherText ?: [NSNull null]), - (self.key ?: [NSNull null]), - (self.algorithm ?: [NSNull null]), - ]; -} -@end - -@implementation DecryptResponse -+ (instancetype)makeWithPlainText:(nullable FlutterStandardTypedData *)plainText { - DecryptResponse* pigeonResult = [[DecryptResponse alloc] init]; - pigeonResult.plainText = plainText; - return pigeonResult; -} -+ (DecryptResponse *)fromList:(NSArray *)list { - DecryptResponse *pigeonResult = [[DecryptResponse alloc] init]; - pigeonResult.plainText = GetNullableObjectAtIndex(list, 0); - return pigeonResult; -} -+ (nullable DecryptResponse *)nullableFromList:(NSArray *)list { - return (list) ? [DecryptResponse fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.plainText ?: [NSNull null]), - ]; -} -@end - -@implementation EncryptFileRequest -+ (instancetype)makeWithPlainTextPath:(nullable NSString *)plainTextPath - cipherTextPath:(nullable NSString *)cipherTextPath - key:(nullable FlutterStandardTypedData *)key - algorithm:(nullable NSString *)algorithm { - EncryptFileRequest* pigeonResult = [[EncryptFileRequest alloc] init]; - pigeonResult.plainTextPath = plainTextPath; - pigeonResult.cipherTextPath = cipherTextPath; - pigeonResult.key = key; - pigeonResult.algorithm = algorithm; - return pigeonResult; -} -+ (EncryptFileRequest *)fromList:(NSArray *)list { - EncryptFileRequest *pigeonResult = [[EncryptFileRequest alloc] init]; - pigeonResult.plainTextPath = GetNullableObjectAtIndex(list, 0); - pigeonResult.cipherTextPath = GetNullableObjectAtIndex(list, 1); - pigeonResult.key = GetNullableObjectAtIndex(list, 2); - pigeonResult.algorithm = GetNullableObjectAtIndex(list, 3); - return pigeonResult; -} -+ (nullable EncryptFileRequest *)nullableFromList:(NSArray *)list { - return (list) ? [EncryptFileRequest fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.plainTextPath ?: [NSNull null]), - (self.cipherTextPath ?: [NSNull null]), - (self.key ?: [NSNull null]), - (self.algorithm ?: [NSNull null]), - ]; -} -@end - -@implementation EncryptFileResponse -+ (instancetype)makeWithSuccess:(nullable NSNumber *)success { - EncryptFileResponse* pigeonResult = [[EncryptFileResponse alloc] init]; - pigeonResult.success = success; - return pigeonResult; -} -+ (EncryptFileResponse *)fromList:(NSArray *)list { - EncryptFileResponse *pigeonResult = [[EncryptFileResponse alloc] init]; - pigeonResult.success = GetNullableObjectAtIndex(list, 0); - return pigeonResult; -} -+ (nullable EncryptFileResponse *)nullableFromList:(NSArray *)list { - return (list) ? [EncryptFileResponse fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.success ?: [NSNull null]), - ]; -} -@end - -@implementation DecryptFileRequest -+ (instancetype)makeWithCipherTextPath:(nullable NSString *)cipherTextPath - plainTextPath:(nullable NSString *)plainTextPath - key:(nullable FlutterStandardTypedData *)key - algorithm:(nullable NSString *)algorithm { - DecryptFileRequest* pigeonResult = [[DecryptFileRequest alloc] init]; - pigeonResult.cipherTextPath = cipherTextPath; - pigeonResult.plainTextPath = plainTextPath; - pigeonResult.key = key; - pigeonResult.algorithm = algorithm; - return pigeonResult; -} -+ (DecryptFileRequest *)fromList:(NSArray *)list { - DecryptFileRequest *pigeonResult = [[DecryptFileRequest alloc] init]; - pigeonResult.cipherTextPath = GetNullableObjectAtIndex(list, 0); - pigeonResult.plainTextPath = GetNullableObjectAtIndex(list, 1); - pigeonResult.key = GetNullableObjectAtIndex(list, 2); - pigeonResult.algorithm = GetNullableObjectAtIndex(list, 3); - return pigeonResult; -} -+ (nullable DecryptFileRequest *)nullableFromList:(NSArray *)list { - return (list) ? [DecryptFileRequest fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.cipherTextPath ?: [NSNull null]), - (self.plainTextPath ?: [NSNull null]), - (self.key ?: [NSNull null]), - (self.algorithm ?: [NSNull null]), - ]; -} -@end - -@implementation DecryptFileResponse -+ (instancetype)makeWithSuccess:(nullable NSNumber *)success { - DecryptFileResponse* pigeonResult = [[DecryptFileResponse alloc] init]; - pigeonResult.success = success; - return pigeonResult; -} -+ (DecryptFileResponse *)fromList:(NSArray *)list { - DecryptFileResponse *pigeonResult = [[DecryptFileResponse alloc] init]; - pigeonResult.success = GetNullableObjectAtIndex(list, 0); - return pigeonResult; -} -+ (nullable DecryptFileResponse *)nullableFromList:(NSArray *)list { - return (list) ? [DecryptFileResponse fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.success ?: [NSNull null]), - ]; -} -@end - -@implementation EncryptWithIVRequest -+ (instancetype)makeWithPlainText:(nullable FlutterStandardTypedData *)plainText - iv:(nullable FlutterStandardTypedData *)iv - key:(nullable FlutterStandardTypedData *)key - algorithm:(nullable NSString *)algorithm { - EncryptWithIVRequest* pigeonResult = [[EncryptWithIVRequest alloc] init]; - pigeonResult.plainText = plainText; - pigeonResult.iv = iv; - pigeonResult.key = key; - pigeonResult.algorithm = algorithm; - return pigeonResult; -} -+ (EncryptWithIVRequest *)fromList:(NSArray *)list { - EncryptWithIVRequest *pigeonResult = [[EncryptWithIVRequest alloc] init]; - pigeonResult.plainText = GetNullableObjectAtIndex(list, 0); - pigeonResult.iv = GetNullableObjectAtIndex(list, 1); - pigeonResult.key = GetNullableObjectAtIndex(list, 2); - pigeonResult.algorithm = GetNullableObjectAtIndex(list, 3); - return pigeonResult; -} -+ (nullable EncryptWithIVRequest *)nullableFromList:(NSArray *)list { - return (list) ? [EncryptWithIVRequest fromList:list] : nil; -} -- (NSArray *)toList { - return @[ - (self.plainText ?: [NSNull null]), - (self.iv ?: [NSNull null]), - (self.key ?: [NSNull null]), - (self.algorithm ?: [NSNull null]), - ]; -} -@end - -@interface NativeCryptoAPICodecReader : FlutterStandardReader -@end -@implementation NativeCryptoAPICodecReader -- (nullable id)readValueOfType:(UInt8)type { - switch (type) { - case 128: - return [DecryptFileRequest fromList:[self readValue]]; - case 129: - return [DecryptFileResponse fromList:[self readValue]]; - case 130: - return [DecryptRequest fromList:[self readValue]]; - case 131: - return [DecryptResponse fromList:[self readValue]]; - case 132: - return [EncryptFileRequest fromList:[self readValue]]; - case 133: - return [EncryptFileResponse fromList:[self readValue]]; - case 134: - return [EncryptRequest fromList:[self readValue]]; - case 135: - return [EncryptResponse fromList:[self readValue]]; - case 136: - return [EncryptWithIVRequest fromList:[self readValue]]; - case 137: - return [GenerateSecureRandomRequest fromList:[self readValue]]; - case 138: - return [GenerateSecureRandomResponse fromList:[self readValue]]; - case 139: - return [HashRequest fromList:[self readValue]]; - case 140: - return [HashResponse fromList:[self readValue]]; - case 141: - return [HmacRequest fromList:[self readValue]]; - case 142: - return [HmacResponse fromList:[self readValue]]; - case 143: - return [Pbkdf2Request fromList:[self readValue]]; - case 144: - return [Pbkdf2Response fromList:[self readValue]]; - default: - return [super readValueOfType:type]; - } -} -@end - -@interface NativeCryptoAPICodecWriter : FlutterStandardWriter -@end -@implementation NativeCryptoAPICodecWriter -- (void)writeValue:(id)value { - if ([value isKindOfClass:[DecryptFileRequest class]]) { - [self writeByte:128]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[DecryptFileResponse class]]) { - [self writeByte:129]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[DecryptRequest class]]) { - [self writeByte:130]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[DecryptResponse class]]) { - [self writeByte:131]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[EncryptFileRequest class]]) { - [self writeByte:132]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[EncryptFileResponse class]]) { - [self writeByte:133]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[EncryptRequest class]]) { - [self writeByte:134]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[EncryptResponse class]]) { - [self writeByte:135]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[EncryptWithIVRequest class]]) { - [self writeByte:136]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[GenerateSecureRandomRequest class]]) { - [self writeByte:137]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[GenerateSecureRandomResponse class]]) { - [self writeByte:138]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[HashRequest class]]) { - [self writeByte:139]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[HashResponse class]]) { - [self writeByte:140]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[HmacRequest class]]) { - [self writeByte:141]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[HmacResponse class]]) { - [self writeByte:142]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[Pbkdf2Request class]]) { - [self writeByte:143]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[Pbkdf2Response class]]) { - [self writeByte:144]; - [self writeValue:[value toList]]; - } else { - [super writeValue:value]; - } -} -@end - -@interface NativeCryptoAPICodecReaderWriter : FlutterStandardReaderWriter -@end -@implementation NativeCryptoAPICodecReaderWriter -- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { - return [[NativeCryptoAPICodecWriter alloc] initWithData:data]; -} -- (FlutterStandardReader *)readerWithData:(NSData *)data { - return [[NativeCryptoAPICodecReader alloc] initWithData:data]; -} -@end - -NSObject *NativeCryptoAPIGetCodec() { - static FlutterStandardMessageCodec *sSharedObject = nil; - static dispatch_once_t sPred = 0; - dispatch_once(&sPred, ^{ - NativeCryptoAPICodecReaderWriter *readerWriter = [[NativeCryptoAPICodecReaderWriter alloc] init]; - sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; - }); - return sSharedObject; -} - -void NativeCryptoAPISetup(id binaryMessenger, NSObject *api) { - { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.NativeCryptoAPI.hash" - binaryMessenger:binaryMessenger - codec:NativeCryptoAPIGetCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(hashRequest:error:)], @"NativeCryptoAPI api (%@) doesn't respond to @selector(hashRequest:error:)", api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - HashRequest *arg_request = GetNullableObjectAtIndex(args, 0); - FlutterError *error; - HashResponse *output = [api hashRequest:arg_request error:&error]; - callback(wrapResult(output, error)); - }]; - } else { - [channel setMessageHandler:nil]; - } - } - { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.NativeCryptoAPI.hmac" - binaryMessenger:binaryMessenger - codec:NativeCryptoAPIGetCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(hmacRequest:error:)], @"NativeCryptoAPI api (%@) doesn't respond to @selector(hmacRequest:error:)", api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - HmacRequest *arg_request = GetNullableObjectAtIndex(args, 0); - FlutterError *error; - HmacResponse *output = [api hmacRequest:arg_request error:&error]; - callback(wrapResult(output, error)); - }]; - } else { - [channel setMessageHandler:nil]; - } - } - { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.NativeCryptoAPI.generateSecureRandom" - binaryMessenger:binaryMessenger - codec:NativeCryptoAPIGetCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(generateSecureRandomRequest:error:)], @"NativeCryptoAPI api (%@) doesn't respond to @selector(generateSecureRandomRequest:error:)", api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - GenerateSecureRandomRequest *arg_request = GetNullableObjectAtIndex(args, 0); - FlutterError *error; - GenerateSecureRandomResponse *output = [api generateSecureRandomRequest:arg_request error:&error]; - callback(wrapResult(output, error)); - }]; - } else { - [channel setMessageHandler:nil]; - } - } - { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.NativeCryptoAPI.pbkdf2" - binaryMessenger:binaryMessenger - codec:NativeCryptoAPIGetCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(pbkdf2Request:error:)], @"NativeCryptoAPI api (%@) doesn't respond to @selector(pbkdf2Request:error:)", api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - Pbkdf2Request *arg_request = GetNullableObjectAtIndex(args, 0); - FlutterError *error; - Pbkdf2Response *output = [api pbkdf2Request:arg_request error:&error]; - callback(wrapResult(output, error)); - }]; - } else { - [channel setMessageHandler:nil]; - } - } - { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.NativeCryptoAPI.encrypt" - binaryMessenger:binaryMessenger - codec:NativeCryptoAPIGetCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(encryptRequest:error:)], @"NativeCryptoAPI api (%@) doesn't respond to @selector(encryptRequest:error:)", api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - EncryptRequest *arg_request = GetNullableObjectAtIndex(args, 0); - FlutterError *error; - EncryptResponse *output = [api encryptRequest:arg_request error:&error]; - callback(wrapResult(output, error)); - }]; - } else { - [channel setMessageHandler:nil]; - } - } - { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.NativeCryptoAPI.decrypt" - binaryMessenger:binaryMessenger - codec:NativeCryptoAPIGetCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(decryptRequest:error:)], @"NativeCryptoAPI api (%@) doesn't respond to @selector(decryptRequest:error:)", api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - DecryptRequest *arg_request = GetNullableObjectAtIndex(args, 0); - FlutterError *error; - DecryptResponse *output = [api decryptRequest:arg_request error:&error]; - callback(wrapResult(output, error)); - }]; - } else { - [channel setMessageHandler:nil]; - } - } - { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.NativeCryptoAPI.encryptFile" - binaryMessenger:binaryMessenger - codec:NativeCryptoAPIGetCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(encryptFileRequest:error:)], @"NativeCryptoAPI api (%@) doesn't respond to @selector(encryptFileRequest:error:)", api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - EncryptFileRequest *arg_request = GetNullableObjectAtIndex(args, 0); - FlutterError *error; - EncryptFileResponse *output = [api encryptFileRequest:arg_request error:&error]; - callback(wrapResult(output, error)); - }]; - } else { - [channel setMessageHandler:nil]; - } - } - { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.NativeCryptoAPI.decryptFile" - binaryMessenger:binaryMessenger - codec:NativeCryptoAPIGetCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(decryptFileRequest:error:)], @"NativeCryptoAPI api (%@) doesn't respond to @selector(decryptFileRequest:error:)", api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - DecryptFileRequest *arg_request = GetNullableObjectAtIndex(args, 0); - FlutterError *error; - DecryptFileResponse *output = [api decryptFileRequest:arg_request error:&error]; - callback(wrapResult(output, error)); - }]; - } else { - [channel setMessageHandler:nil]; - } - } - { - FlutterBasicMessageChannel *channel = - [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.NativeCryptoAPI.encryptWithIV" - binaryMessenger:binaryMessenger - codec:NativeCryptoAPIGetCodec()]; - if (api) { - NSCAssert([api respondsToSelector:@selector(encryptWithIVRequest:error:)], @"NativeCryptoAPI api (%@) doesn't respond to @selector(encryptWithIVRequest:error:)", api); - [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - EncryptWithIVRequest *arg_request = GetNullableObjectAtIndex(args, 0); - FlutterError *error; - EncryptResponse *output = [api encryptWithIVRequest:arg_request error:&error]; - callback(wrapResult(output, error)); - }]; - } else { - [channel setMessageHandler:nil]; - } - } -} diff --git a/packages/native_crypto_ios/ios/Classes/messages.g.swift b/packages/native_crypto_ios/ios/Classes/messages.g.swift new file mode 100644 index 0000000..f9c5a5d --- /dev/null +++ b/packages/native_crypto_ios/ios/Classes/messages.g.swift @@ -0,0 +1,243 @@ +// Copyright 2019-2023 Hugo Pointcheval +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. +// -- +// Autogenerated from Pigeon (v9.2.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation +#if os(iOS) +import Flutter +#elseif os(macOS) +import FlutterMacOS +#else +#error("Unsupported platform.") +#endif + + + +private func wrapResult(_ result: Any?) -> [Any?] { + return [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)" + ] +} + +enum HashAlgorithm: Int { + case sha256 = 0 + case sha384 = 1 + case sha512 = 2 +} + +enum CipherAlgorithm: Int { + case aes = 0 +} +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol NativeCryptoAPI { + func hash(data: FlutterStandardTypedData, algorithm: HashAlgorithm) throws -> FlutterStandardTypedData? + func hmac(data: FlutterStandardTypedData, key: FlutterStandardTypedData, algorithm: HashAlgorithm) throws -> FlutterStandardTypedData? + func generateSecureRandom(length: Int64) throws -> FlutterStandardTypedData? + func pbkdf2(password: FlutterStandardTypedData, salt: FlutterStandardTypedData, length: Int64, iterations: Int64, algorithm: HashAlgorithm) throws -> FlutterStandardTypedData? + func encrypt(plainText: FlutterStandardTypedData, key: FlutterStandardTypedData, algorithm: CipherAlgorithm) throws -> FlutterStandardTypedData? + func encryptWithIV(plainText: FlutterStandardTypedData, iv: FlutterStandardTypedData, key: FlutterStandardTypedData, algorithm: CipherAlgorithm) throws -> FlutterStandardTypedData? + func decrypt(cipherText: FlutterStandardTypedData, key: FlutterStandardTypedData, algorithm: CipherAlgorithm) throws -> FlutterStandardTypedData? + func encryptFile(plainTextPath: String, cipherTextPath: String, key: FlutterStandardTypedData, algorithm: CipherAlgorithm) throws -> Bool? + func encryptFileWithIV(plainTextPath: String, cipherTextPath: String, iv: FlutterStandardTypedData, key: FlutterStandardTypedData, algorithm: CipherAlgorithm) throws -> Bool? + func decryptFile(cipherTextPath: String, plainTextPath: String, key: FlutterStandardTypedData, algorithm: CipherAlgorithm) throws -> Bool? +} + +/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. +class NativeCryptoAPISetup { + /// The codec used by NativeCryptoAPI. + /// Sets up an instance of `NativeCryptoAPI` to handle messages through the `binaryMessenger`. + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: NativeCryptoAPI?) { + let hashChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.NativeCryptoAPI.hash", binaryMessenger: binaryMessenger) + if let api = api { + hashChannel.setMessageHandler { message, reply in + let args = message as! [Any] + let dataArg = args[0] as! FlutterStandardTypedData + let algorithmArg = HashAlgorithm(rawValue: args[1] as! Int)! + do { + let result = try api.hash(data: dataArg, algorithm: algorithmArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + hashChannel.setMessageHandler(nil) + } + let hmacChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.NativeCryptoAPI.hmac", binaryMessenger: binaryMessenger) + if let api = api { + hmacChannel.setMessageHandler { message, reply in + let args = message as! [Any] + let dataArg = args[0] as! FlutterStandardTypedData + let keyArg = args[1] as! FlutterStandardTypedData + let algorithmArg = HashAlgorithm(rawValue: args[2] as! Int)! + do { + let result = try api.hmac(data: dataArg, key: keyArg, algorithm: algorithmArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + hmacChannel.setMessageHandler(nil) + } + let generateSecureRandomChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.NativeCryptoAPI.generateSecureRandom", binaryMessenger: binaryMessenger) + if let api = api { + generateSecureRandomChannel.setMessageHandler { message, reply in + let args = message as! [Any] + let lengthArg = (args[0] is Int) ? Int64(args[0] as! Int) : args[0] as! Int64 + do { + let result = try api.generateSecureRandom(length: lengthArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + generateSecureRandomChannel.setMessageHandler(nil) + } + let pbkdf2Channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.NativeCryptoAPI.pbkdf2", binaryMessenger: binaryMessenger) + if let api = api { + pbkdf2Channel.setMessageHandler { message, reply in + let args = message as! [Any] + let passwordArg = args[0] as! FlutterStandardTypedData + let saltArg = args[1] as! FlutterStandardTypedData + let lengthArg = (args[2] is Int) ? Int64(args[2] as! Int) : args[2] as! Int64 + let iterationsArg = (args[3] is Int) ? Int64(args[3] as! Int) : args[3] as! Int64 + let algorithmArg = HashAlgorithm(rawValue: args[4] as! Int)! + do { + let result = try api.pbkdf2(password: passwordArg, salt: saltArg, length: lengthArg, iterations: iterationsArg, algorithm: algorithmArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + pbkdf2Channel.setMessageHandler(nil) + } + let encryptChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.NativeCryptoAPI.encrypt", binaryMessenger: binaryMessenger) + if let api = api { + encryptChannel.setMessageHandler { message, reply in + let args = message as! [Any] + let plainTextArg = args[0] as! FlutterStandardTypedData + let keyArg = args[1] as! FlutterStandardTypedData + let algorithmArg = CipherAlgorithm(rawValue: args[2] as! Int)! + do { + let result = try api.encrypt(plainText: plainTextArg, key: keyArg, algorithm: algorithmArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + encryptChannel.setMessageHandler(nil) + } + let encryptWithIVChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.NativeCryptoAPI.encryptWithIV", binaryMessenger: binaryMessenger) + if let api = api { + encryptWithIVChannel.setMessageHandler { message, reply in + let args = message as! [Any] + let plainTextArg = args[0] as! FlutterStandardTypedData + let ivArg = args[1] as! FlutterStandardTypedData + let keyArg = args[2] as! FlutterStandardTypedData + let algorithmArg = CipherAlgorithm(rawValue: args[3] as! Int)! + do { + let result = try api.encryptWithIV(plainText: plainTextArg, iv: ivArg, key: keyArg, algorithm: algorithmArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + encryptWithIVChannel.setMessageHandler(nil) + } + let decryptChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.NativeCryptoAPI.decrypt", binaryMessenger: binaryMessenger) + if let api = api { + decryptChannel.setMessageHandler { message, reply in + let args = message as! [Any] + let cipherTextArg = args[0] as! FlutterStandardTypedData + let keyArg = args[1] as! FlutterStandardTypedData + let algorithmArg = CipherAlgorithm(rawValue: args[2] as! Int)! + do { + let result = try api.decrypt(cipherText: cipherTextArg, key: keyArg, algorithm: algorithmArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + decryptChannel.setMessageHandler(nil) + } + let encryptFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.NativeCryptoAPI.encryptFile", binaryMessenger: binaryMessenger) + if let api = api { + encryptFileChannel.setMessageHandler { message, reply in + let args = message as! [Any] + let plainTextPathArg = args[0] as! String + let cipherTextPathArg = args[1] as! String + let keyArg = args[2] as! FlutterStandardTypedData + let algorithmArg = CipherAlgorithm(rawValue: args[3] as! Int)! + do { + let result = try api.encryptFile(plainTextPath: plainTextPathArg, cipherTextPath: cipherTextPathArg, key: keyArg, algorithm: algorithmArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + encryptFileChannel.setMessageHandler(nil) + } + let encryptFileWithIVChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.NativeCryptoAPI.encryptFileWithIV", binaryMessenger: binaryMessenger) + if let api = api { + encryptFileWithIVChannel.setMessageHandler { message, reply in + let args = message as! [Any] + let plainTextPathArg = args[0] as! String + let cipherTextPathArg = args[1] as! String + let ivArg = args[2] as! FlutterStandardTypedData + let keyArg = args[3] as! FlutterStandardTypedData + let algorithmArg = CipherAlgorithm(rawValue: args[4] as! Int)! + do { + let result = try api.encryptFileWithIV(plainTextPath: plainTextPathArg, cipherTextPath: cipherTextPathArg, iv: ivArg, key: keyArg, algorithm: algorithmArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + encryptFileWithIVChannel.setMessageHandler(nil) + } + let decryptFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.NativeCryptoAPI.decryptFile", binaryMessenger: binaryMessenger) + if let api = api { + decryptFileChannel.setMessageHandler { message, reply in + let args = message as! [Any] + let cipherTextPathArg = args[0] as! String + let plainTextPathArg = args[1] as! String + let keyArg = args[2] as! FlutterStandardTypedData + let algorithmArg = CipherAlgorithm(rawValue: args[3] as! Int)! + do { + let result = try api.decryptFile(cipherTextPath: cipherTextPathArg, plainTextPath: plainTextPathArg, key: keyArg, algorithm: algorithmArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + decryptFileChannel.setMessageHandler(nil) + } + } +} diff --git a/packages/native_crypto_ios/ios/Classes/protocols/Cipher.swift b/packages/native_crypto_ios/ios/Classes/protocols/Cipher.swift index f1291f9..024c5f8 100644 --- a/packages/native_crypto_ios/ios/Classes/protocols/Cipher.swift +++ b/packages/native_crypto_ios/ios/Classes/protocols/Cipher.swift @@ -8,9 +8,8 @@ import Foundation protocol Cipher { - var algorithm: CipherAlgorithm { get } - func encrypt(data: Data, key: Data) throws -> Data + func encrypt(data: Data, key: Data, predefinedIV: Data?) throws -> Data func decrypt(data: Data, key: Data) throws -> Data - func encryptAsList(data: Data, key: Data) throws -> [Data] - func decryptAsList(data: [Data], key: Data) throws-> Data + func encryptFile(fileParameters: FileParameters, key: Data, predefinedIV: Data?) throws -> Bool + func decryptFile(fileParameters: FileParameters, key: Data) throws -> Bool } diff --git a/packages/native_crypto_ios/ios/Classes/protocols/Key.swift b/packages/native_crypto_ios/ios/Classes/protocols/Key.swift deleted file mode 100644 index 9fc9199..0000000 --- a/packages/native_crypto_ios/ios/Classes/protocols/Key.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// Key.swift -// native_crypto_ios -// -// Created by Hugo Pointcheval on 25/05/2022. -// - -import Foundation - -protocol Key { - var bytes: Data { get set } -} diff --git a/packages/native_crypto_ios/ios/Classes/protocols/KeyDerivation.swift b/packages/native_crypto_ios/ios/Classes/protocols/KeyDerivation.swift index df3a0d5..f5ff3fb 100644 --- a/packages/native_crypto_ios/ios/Classes/protocols/KeyDerivation.swift +++ b/packages/native_crypto_ios/ios/Classes/protocols/KeyDerivation.swift @@ -8,6 +8,5 @@ import Foundation protocol KeyDerivation { - var algorithm : KdfAlgorithm { get } - func derive() throws -> SecretKey + func derive() throws -> Data? } diff --git a/packages/native_crypto_ios/ios/Classes/utils/CipherAlgorithm.swift b/packages/native_crypto_ios/ios/Classes/utils/CipherAlgorithm.swift deleted file mode 100644 index afb9094..0000000 --- a/packages/native_crypto_ios/ios/Classes/utils/CipherAlgorithm.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// CipherAlgorithm.swift -// native_crypto_ios -// -// Created by Hugo Pointcheval on 25/05/2022. -// - -import Foundation - -enum CipherAlgorithm : String { - case aes = "aes" - - var getCipher: Cipher { - switch self { - case .aes: return AESCipher() - } - } -} diff --git a/packages/native_crypto_ios/ios/Classes/utils/FileParameters.swift b/packages/native_crypto_ios/ios/Classes/utils/FileParameters.swift index efbc0ae..dbdbf29 100644 --- a/packages/native_crypto_ios/ios/Classes/utils/FileParameters.swift +++ b/packages/native_crypto_ios/ios/Classes/utils/FileParameters.swift @@ -6,3 +6,15 @@ // import Foundation + +class FileParameters { + var inputPath: String + var outputPath: String + + init(input: String, output: String) { + self.inputPath = input + self.outputPath = output + } + + +} diff --git a/packages/native_crypto_ios/ios/Classes/utils/HashAlgorithm.swift b/packages/native_crypto_ios/ios/Classes/utils/HashAlgorithm.swift deleted file mode 100644 index 38b7740..0000000 --- a/packages/native_crypto_ios/ios/Classes/utils/HashAlgorithm.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// HashAlgorithm.swift -// native_crypto_ios -// -// Created by Hugo Pointcheval on 25/05/2022. -// - -import Foundation -import CommonCrypto -import CryptoKit - -enum HashAlgorithm: String { - case HashSHA256 = "sha256" - case HashSHA384 = "sha384" - case HashSHA512 = "sha512" - - var pbkdf2identifier: UInt32 { - switch self { - case .HashSHA256: return CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256) - case .HashSHA384: return CCPBKDFAlgorithm(kCCPRFHmacAlgSHA384) - case .HashSHA512: return CCPBKDFAlgorithm(kCCPRFHmacAlgSHA512) - } - } - - @available(iOS 13.0, *) - func digest(data: Data) -> Data { - switch self { - case .HashSHA256: - return Data(SHA256.hash(data: data)) - case .HashSHA384: - return Data(SHA384.hash(data: data)) - case .HashSHA512: - return Data(SHA512.hash(data: data)) - } - } - - @available(iOS 13.0, *) - static func digest(data: Data, algorithm: String) throws -> Data { - let algo = HashAlgorithm.init(rawValue: algorithm) - if (algo == nil) { - throw NativeCryptoError.messageDigestError - } - return algo!.digest(data: data) - } -} diff --git a/packages/native_crypto_ios/ios/Classes/utils/HashAlgorithmParser.swift b/packages/native_crypto_ios/ios/Classes/utils/HashAlgorithmParser.swift new file mode 100644 index 0000000..52e160e --- /dev/null +++ b/packages/native_crypto_ios/ios/Classes/utils/HashAlgorithmParser.swift @@ -0,0 +1,31 @@ +// +// HashAlgorithmParser.swift +// native_crypto_ios +// +// Created by Hugo Pointcheval on 04/04/2023. +// + +import Foundation +import CommonCrypto +import CryptoKit + +public class HashAlgorithmParser { + static func getMessageDigest(algorithm: HashAlgorithm) -> any HashFunction { + switch algorithm { + case .sha256: return SHA256.init() + case .sha384: return SHA384.init() + case .sha512: return SHA512.init() + @unknown default: fatalError("Unknown algorithm") + } + } + + static func getPbkdf2Identifier(algorithm: HashAlgorithm) -> UInt32 { + switch algorithm { + case .sha256: return CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256) + case .sha384: return CCPBKDFAlgorithm(kCCPRFHmacAlgSHA384) + case .sha512: return CCPBKDFAlgorithm(kCCPRFHmacAlgSHA512) + @unknown default: fatalError("Unknown algorithm") + } + } + +} diff --git a/packages/native_crypto_ios/ios/Classes/utils/KdfAlgorithm.swift b/packages/native_crypto_ios/ios/Classes/utils/KdfAlgorithm.swift deleted file mode 100644 index d6af3c1..0000000 --- a/packages/native_crypto_ios/ios/Classes/utils/KdfAlgorithm.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// KdfAlgorithm.swift -// native_crypto_ios -// -// Created by Hugo Pointcheval on 25/05/2022. -// - -import Foundation - -enum KdfAlgorithm { - case pbkdf2 -} diff --git a/packages/native_crypto_ios/ios/Classes/utils/NativeCryptoError.swift b/packages/native_crypto_ios/ios/Classes/utils/NativeCryptoError.swift index a2ac159..0a10b00 100644 --- a/packages/native_crypto_ios/ios/Classes/utils/NativeCryptoError.swift +++ b/packages/native_crypto_ios/ios/Classes/utils/NativeCryptoError.swift @@ -7,12 +7,51 @@ import Foundation -enum NativeCryptoError : Error { -case decryptionError -case encryptionError -case messageDigestError -case pbkdf2Error -case cipherError -case resultError -case exceptionError +enum NativeCryptoError : LocalizedError { + /// When an operation is not supported + case notSupported(reason: String? = nil) + /// When the key is invalid + case invalidKey(reason: String? = nil) + /// When the key length is invalid + case invalidKeySize(reason: String? = nil) + /// When operation parameter is invalid + case invalidParameter(reason: String? = nil) + /// When an authentication process fails + case authenticationError(reason: String? = nil) + /// When a input/output process (like file manipulation) fails + case ioError(reason: String? = nil) + /// When cipher initialization fails + case cipherError(reason: String? = nil) + /// When a digest process fails + case digestError(reason: String? = nil) + /// When a key derivation process fails + case kdfError(reason: String? = nil) + /// When any other expection is thrown + case unknownError(reason: String? = nil) + + var errorDescription: String? { + switch self { + case .notSupported(reason: let reason): + return reason ?? "This operation is not supported." + case .invalidKey(reason: let reason): + return reason ?? "Invalid key." + case .invalidKeySize(reason: let reason): + return reason ?? "Invalid key size." + case .invalidParameter(reason: let reason): + return reason ?? "Invalid parameter." + case .authenticationError(reason: let reason): + return reason ?? "Authentication fails." + case .ioError(reason: let reason): + return reason ?? "IO operation fails." + case .cipherError(reason: let reason): + return reason ?? "Cipher initialization fails." + case .digestError(reason: let reason): + return reason ?? "Digest fails." + case .kdfError(reason: let reason): + return reason ?? "Key derivation fails." + case .unknownError(reason: let reason): + return reason ?? "An unknown error occurred during the operation." + } + } + } diff --git a/packages/native_crypto_ios/ios/Classes/utils/Task.swift b/packages/native_crypto_ios/ios/Classes/utils/Task.swift index 4d11070..4a9d049 100644 --- a/packages/native_crypto_ios/ios/Classes/utils/Task.swift +++ b/packages/native_crypto_ios/ios/Classes/utils/Task.swift @@ -1,10 +1,3 @@ -// -// Task.swift -// native_crypto_ios -// -// Created by Hugo Pointcheval on 25/05/2022. -// - import Foundation class Task { @@ -30,7 +23,7 @@ class Task { if (exception != nil) { return exception! } else { - return NativeCryptoError.exceptionError + return NativeCryptoError.unknownError() } }