From 871e3b74edef617614fca328c53047fff4d2c74c Mon Sep 17 00:00:00 2001 From: Pointcheval Hugo Date: Sat, 8 May 2021 20:11:28 +0200 Subject: [PATCH] Add RSA keys generation --- ios/Classes/KeyGeneration.swift | 34 +++++++++++++++++++++++ ios/Classes/SwiftNativeCryptoPlugin.swift | 25 +++++++++++++++++ lib/src/asym/RSA.dart | 5 +++- lib/src/platform.dart | 5 ++-- 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/ios/Classes/KeyGeneration.swift b/ios/Classes/KeyGeneration.swift index a918f9b..76e0325 100644 --- a/ios/Classes/KeyGeneration.swift +++ b/ios/Classes/KeyGeneration.swift @@ -7,6 +7,7 @@ // Author: Hugo Pointcheval // import Foundation +import CommonCrypto class KeyGeneration { func keygen(size : NSNumber) -> Data? { @@ -22,4 +23,37 @@ class KeyGeneration { } return nil } + + @available(iOS 10.0, watchOS 3.0, tvOS 10.0, *) + func rsaKeypairGen(size : NSNumber) throws -> [Data]? { + + let tagData = UUID().uuidString.data(using: .utf8) + + let isPermanent = true + + let attributes: [CFString: Any] = [ + kSecAttrKeyType: kSecAttrKeyTypeRSA, + kSecAttrKeySizeInBits: (size.intValue * 8), + kSecPrivateKeyAttrs: [ + kSecAttrIsPermanent: isPermanent, + kSecAttrApplicationTag: tagData! + ] + ] + + var error: Unmanaged? + guard let privKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else { + throw error!.takeRetainedValue() as Error + } + let pubKey = SecKeyCopyPublicKey(privKey) + + + var errorExport: Unmanaged? + let data1 = SecKeyCopyExternalRepresentation(pubKey!, &errorExport) + let unwrappedData1 = data1 as Data? + + let data2 = SecKeyCopyExternalRepresentation(privKey, &errorExport) + let unwrappedData2 = data2 as Data? + + return [unwrappedData1!, unwrappedData2!] + } } diff --git a/ios/Classes/SwiftNativeCryptoPlugin.swift b/ios/Classes/SwiftNativeCryptoPlugin.swift index 63889d8..f33cb88 100644 --- a/ios/Classes/SwiftNativeCryptoPlugin.swift +++ b/ios/Classes/SwiftNativeCryptoPlugin.swift @@ -79,6 +79,31 @@ public class SwiftNativeCryptoPlugin: NSObject, FlutterPlugin { message: "GENERATED KEY IS NIL.", details: nil)) } + case "rsaKeypairGen": + let args = call.arguments as! NSDictionary + + let size = args["size"] as! NSNumber + + let keypair : [Data]? + + if #available(iOS 10.0, *) { + do { + keypair = try KeyGeneration().rsaKeypairGen(size: size) + } catch { + keypair = nil + } + } else { + // Fallback on earlier versions + keypair = nil + } + + if keypair != nil { + result(keypair) + } else { + result(FlutterError(code: "KEYPAIRGENERROR", + message: "GENERATED KEYPAIR IS EMPTY.", + details: nil)) + } case "encrypt": let args = call.arguments as! NSDictionary diff --git a/lib/src/asym/RSA.dart b/lib/src/asym/RSA.dart index d09bd4d..96a1db3 100644 --- a/lib/src/asym/RSA.dart +++ b/lib/src/asym/RSA.dart @@ -61,7 +61,7 @@ class RSAKeyEncapsulationMechanism implements KeyEncapsulationMechanism { @override Future encapsulate() { - if (!_isInit) { + if (!_isInit || _mode == KemMode.DECAPSULATION) { throw KemInitException("KEM not properly initialized."); } throw UnimplementedError(); @@ -69,6 +69,9 @@ class RSAKeyEncapsulationMechanism implements KeyEncapsulationMechanism { @override Future decapsulate(Encapsulation encapsulation) { + if (!_isInit || _mode == KemMode.ENCAPSULATION) { + throw KemInitException("KEM not properly initialized."); + } throw UnimplementedError(); } } diff --git a/lib/src/platform.dart b/lib/src/platform.dart index 9c94268..ff3a75f 100644 --- a/lib/src/platform.dart +++ b/lib/src/platform.dart @@ -99,7 +99,7 @@ class Platform { Future> rsaKeypairGen(int size) async { try { final List keypair = - await call('rsaKeypairGen', { + await callList('rsaKeypairGen', { 'size': size, }); return keypair; @@ -146,8 +146,7 @@ class Platform { CipherParameters parameters, ) async { try { - final Uint8List data = - await _channel.invokeMethod('decrypt', { + final Uint8List data = await call('decrypt', { 'payload': payload, 'key': key, 'algorithm': algorithm.name,