115 lines
4.7 KiB
Swift

//
// 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<SHA256>(key: symmetricKey).finalize()))
case .sha384: return FlutterStandardTypedData(bytes: Data(HMAC<SHA384>(key: symmetricKey).finalize()))
case .sha512: return FlutterStandardTypedData(bytes: Data(HMAC<SHA512>(key: symmetricKey).finalize()))
@unknown default: fatalError("Unknown algorithm")
}
}
func generateSecureRandom(length: Int64) throws -> FlutterStandardTypedData? {
let lengthInt = Int(truncatingIfNeeded: length)
let bitCount = lengthInt * 8
let symmetricKey = SymmetricKey.init(size: SymmetricKeySize(bitCount: bitCount))
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
}
}