Skip to content

Commit

Permalink
Merge pull request #37 from hoc081098/crypto_ios
Browse files Browse the repository at this point in the history
Add crypto impl for iOS
  • Loading branch information
hoc081098 authored Jun 3, 2022
2 parents 7014f65 + aa028d8 commit 36fa999
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 3 deletions.
2 changes: 2 additions & 0 deletions ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ target 'Runner' do
use_modular_headers!

flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

pod 'CryptoSwift', '~> 1.2.0'
end

post_install do |installer|
Expand Down
9 changes: 8 additions & 1 deletion ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
PODS:
- CryptoSwift (1.2.0)
- Flutter (1.0.0)
- image_picker_ios (0.0.1):
- Flutter
- shared_preferences_ios (0.0.1):
- Flutter

DEPENDENCIES:
- CryptoSwift (~> 1.2.0)
- Flutter (from `Flutter`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)

SPEC REPOS:
trunk:
- CryptoSwift

EXTERNAL SOURCES:
Flutter:
:path: Flutter
Expand All @@ -19,10 +25,11 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/shared_preferences_ios/ios"

SPEC CHECKSUMS:
CryptoSwift: 40e374e45291d8dceedcb0d6184da94533eaabdf
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad

PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
PODFILE CHECKSUM: 28949384d1a9817c5c0092fcf6ffc3a836337eb0

COCOAPODS: 1.11.2
3 changes: 1 addition & 2 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 51;
objects = {

/* Begin PBXBuildFile section */
Expand Down Expand Up @@ -68,7 +68,6 @@
81B81E118F31476FA4045A87 /* Pods-Runner.release.xcconfig */,
A4FEFEB72D9AAEB411E9065F /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
Expand Down
143 changes: 143 additions & 0 deletions ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,156 @@
import UIKit
import Flutter
import CryptoSwift

private extension String {
static let CRYPTO_CHANNEL = "com.hoc.node_auth/crypto"
static let CRYPTO_ERROR_CODE = "com.hoc.node_auth/crypto_error"
static let ENCRYPT_METHOD = "encrypt"
static let DECRYPT_METHOD = "decrypt"
}

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let flutterVC = window?.rootViewController as! FlutterViewController

let cryptoChannel = FlutterMethodChannel(
name: .CRYPTO_CHANNEL,
binaryMessenger: flutterVC.binaryMessenger
)
cryptoChannel.setMethodCallHandler { call, result in
switch call.method {
case .ENCRYPT_METHOD: encrypt(call: call, result: result)
case .DECRYPT_METHOD: decrypt(call: call, result: result)
default:
result(FlutterMethodNotImplemented)
}
}

GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

private enum AESConfig {
static let iv: [UInt8] = "_hoc081098_auth_".bytes
static let key: [UInt8] = "__hoc081098_nodejs_auth_rxdart__".bytes

static let backgroundQueue = DispatchQueue.global(qos: .userInitiated)

static func gcm() -> GCM { GCM(iv: AESConfig.iv, mode: .combined) }
}

private func complete(result: @escaping FlutterResult, with error: Error) {
NSLog("\n[NODE_AUTH] Error: \(error)")

executeOnMain {
result(
FlutterError(
code: .CRYPTO_ERROR_CODE,
message: error.localizedDescription,
details: nil
)
)
}
}

private func executeOnMain(block: @escaping () -> Void) {
if Thread.isMainThread {
block()
} else {
DispatchQueue.main.async {
block()
}
}
}

private func useAES(
input: String,
result: @escaping FlutterResult,
inputToBytes: (String) -> [UInt8]?,
bytesToString: @escaping ([UInt8]) -> String?,
block: @escaping (AES, [UInt8]) throws -> [UInt8]
) {
guard let inputBytes = inputToBytes(input) else {
NSLog("\n[NODE_AUTH] Error: inputToBytes returns nil")

executeOnMain {
result(
FlutterError(
code: .CRYPTO_ERROR_CODE,
message: "An unexpected error occurred!",
details: nil
)
)
}
return
}

AESConfig.backgroundQueue.async {
let start = DispatchTime.now()

do {
let aes = try AES(
key: AESConfig.key,
blockMode: AESConfig.gcm(),
padding: .noPadding
)

let outputBytes = try block(aes, inputBytes)
guard let stringResult = bytesToString(outputBytes) else {
NSLog("\n[NODE_AUTH] Error: bytesToString returns nil")

executeOnMain {
result(
FlutterError(
code: .CRYPTO_ERROR_CODE,
message: "An unexpected error occurred!",
details: nil
)
)
}
return
}

let end = DispatchTime.now()
let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
let millisTime = Double(nanoTime) / 1_000_000
NSLog("\n[NODE_AUTH] Time: \(millisTime) ms")

executeOnMain { result(stringResult) }
} catch {
complete(result: result, with: error)
}
}
}

private func encrypt(call: FlutterMethodCall, result: @escaping FlutterResult) {
useAES(
input: call.arguments as! String,
result: result,
inputToBytes: { $0.bytes },
bytesToString: base64Encode(bytes:)
) { aes, bytes in try aes.encrypt(bytes) }
}


private func decrypt(call: FlutterMethodCall, result: @escaping FlutterResult) {
useAES(
input: call.arguments as! String,
result: result,
inputToBytes: base64Decode(s:),
bytesToString: { .init(bytes: $0, encoding: .utf8) }
) { aes, bytes in try aes.decrypt(bytes) }
}

func base64Decode(s: String) -> [UInt8]? {
Data(base64Encoded: s)?.bytes
}

func base64Encode(bytes: [UInt8]) -> String {
Data(bytes).base64EncodedString()
}

0 comments on commit 36fa999

Please sign in to comment.