Add plugin sources
This commit is contained in:
		
							parent
							
								
									bec8e2100a
								
							
						
					
					
						commit
						842c9ecf4f
					
				
							
								
								
									
										8
									
								
								android/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								android/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
*.iml
 | 
			
		||||
.gradle
 | 
			
		||||
/local.properties
 | 
			
		||||
/.idea/workspace.xml
 | 
			
		||||
/.idea/libraries
 | 
			
		||||
.DS_Store
 | 
			
		||||
/build
 | 
			
		||||
/captures
 | 
			
		||||
							
								
								
									
										44
									
								
								android/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								android/build.gradle
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
group 'fr.pointcheval.native_crypto'
 | 
			
		||||
version '1.0-SNAPSHOT'
 | 
			
		||||
 | 
			
		||||
buildscript {
 | 
			
		||||
    ext.kotlin_version = '1.3.50'
 | 
			
		||||
    repositories {
 | 
			
		||||
        google()
 | 
			
		||||
        jcenter()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dependencies {
 | 
			
		||||
        classpath 'com.android.tools.build:gradle:3.5.0'
 | 
			
		||||
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rootProject.allprojects {
 | 
			
		||||
    repositories {
 | 
			
		||||
        google()
 | 
			
		||||
        jcenter()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
apply plugin: 'com.android.library'
 | 
			
		||||
apply plugin: 'kotlin-android'
 | 
			
		||||
 | 
			
		||||
android {
 | 
			
		||||
    compileSdkVersion 28
 | 
			
		||||
 | 
			
		||||
    sourceSets {
 | 
			
		||||
        main.java.srcDirs += 'src/main/kotlin'
 | 
			
		||||
    }
 | 
			
		||||
    defaultConfig {
 | 
			
		||||
        minSdkVersion 16
 | 
			
		||||
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 | 
			
		||||
    }
 | 
			
		||||
    lintOptions {
 | 
			
		||||
        disable 'InvalidPackage'
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								android/gradle.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								android/gradle.properties
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
org.gradle.jvmargs=-Xmx1536M
 | 
			
		||||
android.enableR8=true
 | 
			
		||||
android.useAndroidX=true
 | 
			
		||||
android.enableJetifier=true
 | 
			
		||||
							
								
								
									
										5
									
								
								android/gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								android/gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
distributionBase=GRADLE_USER_HOME
 | 
			
		||||
distributionPath=wrapper/dists
 | 
			
		||||
zipStoreBase=GRADLE_USER_HOME
 | 
			
		||||
zipStorePath=wrapper/dists
 | 
			
		||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
 | 
			
		||||
							
								
								
									
										1
									
								
								android/settings.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								android/settings.gradle
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
rootProject.name = 'native_crypto'
 | 
			
		||||
							
								
								
									
										3
									
								
								android/src/main/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								android/src/main/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
  package="fr.pointcheval.native_crypto">
 | 
			
		||||
</manifest>
 | 
			
		||||
@ -0,0 +1,135 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2020
 | 
			
		||||
 * Author: Hugo Pointcheval
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package fr.pointcheval.native_crypto
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.NonNull
 | 
			
		||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
 | 
			
		||||
import io.flutter.plugin.common.MethodCall
 | 
			
		||||
import io.flutter.plugin.common.MethodChannel
 | 
			
		||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
 | 
			
		||||
import io.flutter.plugin.common.MethodChannel.Result
 | 
			
		||||
import io.flutter.plugin.common.PluginRegistry.Registrar
 | 
			
		||||
import java.security.MessageDigest
 | 
			
		||||
import java.security.SecureRandom
 | 
			
		||||
import javax.crypto.Cipher
 | 
			
		||||
import javax.crypto.KeyGenerator
 | 
			
		||||
import javax.crypto.SecretKey
 | 
			
		||||
import javax.crypto.spec.IvParameterSpec
 | 
			
		||||
import javax.crypto.spec.SecretKeySpec
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** NativeCryptoPlugin */
 | 
			
		||||
public class NativeCryptoPlugin : FlutterPlugin, MethodCallHandler {
 | 
			
		||||
    // CRYPTO CONSTS
 | 
			
		||||
    private val HASH_FUNC = "SHA-256"
 | 
			
		||||
    private val SYM_CRYPTO_METHOD = "AES"
 | 
			
		||||
    private val SYM_CRYPTO_PADDING = "AES/CBC/PKCS5PADDING"
 | 
			
		||||
    private val SYM_CRYPTO_BITS = 256
 | 
			
		||||
 | 
			
		||||
    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
 | 
			
		||||
        val channel = MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "native.crypto.helper")
 | 
			
		||||
        channel.setMethodCallHandler(NativeCryptoPlugin());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        @JvmStatic
 | 
			
		||||
        fun registerWith(registrar: Registrar) {
 | 
			
		||||
            val channel = MethodChannel(registrar.messenger(), "native.crypto.helper")
 | 
			
		||||
            channel.setMethodCallHandler(NativeCryptoPlugin())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
 | 
			
		||||
        if (call.method == "symKeygen") {
 | 
			
		||||
            val aesKey = symKeygen() // Collection<ByteArray>
 | 
			
		||||
 | 
			
		||||
            if (aesKey.isNotEmpty()) {
 | 
			
		||||
                result.success(aesKey)
 | 
			
		||||
            } else {
 | 
			
		||||
                result.error("KeygenError", "Key generation failed.", null)
 | 
			
		||||
            }
 | 
			
		||||
        } else if (call.method == "symEncrypt") {
 | 
			
		||||
            val payload = call.argument<ByteArray>("payload") // ByteArray
 | 
			
		||||
            val aesKey = call.argument<ByteArray>("aesKey") // ByteArray
 | 
			
		||||
 | 
			
		||||
            val encryptedPayload = symEncrypt(payload!!, aesKey!!) // Collection<ByteArray>
 | 
			
		||||
 | 
			
		||||
            if (encryptedPayload.isNotEmpty()) {
 | 
			
		||||
                result.success(encryptedPayload)
 | 
			
		||||
            } else {
 | 
			
		||||
                result.error("EncryptionError", "Encryption failed.", null)
 | 
			
		||||
            }
 | 
			
		||||
        } else if (call.method == "symDecrypt") {
 | 
			
		||||
            val payload = call.argument<Collection<ByteArray>>("payload") // Collection<ByteArray>
 | 
			
		||||
            val aesKey = call.argument<ByteArray>("aesKey") // ByteArray
 | 
			
		||||
 | 
			
		||||
            val decryptedPayload = symDecrypt(payload!!, aesKey!!) // ByteArray
 | 
			
		||||
 | 
			
		||||
            if (decryptedPayload != null && decryptedPayload.isNotEmpty()) {
 | 
			
		||||
                result.success(decryptedPayload)
 | 
			
		||||
            } else {
 | 
			
		||||
                result.error("DecryptionError", "Decryption failed.", null)
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            result.notImplemented()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // CRYPTO NATIVE FUNCTIONS
 | 
			
		||||
 | 
			
		||||
    private fun digest(obj: ByteArray?): ByteArray {
 | 
			
		||||
        val md = MessageDigest.getInstance(HASH_FUNC)
 | 
			
		||||
        return md.digest(obj)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun symKeygen(): ByteArray {
 | 
			
		||||
 | 
			
		||||
        val secureRandom = SecureRandom()
 | 
			
		||||
        val keyGenerator = KeyGenerator.getInstance(SYM_CRYPTO_METHOD)
 | 
			
		||||
        keyGenerator?.init(SYM_CRYPTO_BITS, secureRandom)
 | 
			
		||||
        val skey = keyGenerator?.generateKey()
 | 
			
		||||
 | 
			
		||||
        return skey!!.encoded
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private fun symEncrypt(payload: ByteArray, aesKey: ByteArray): Collection<ByteArray> {
 | 
			
		||||
 | 
			
		||||
        val mac = digest(aesKey + payload)
 | 
			
		||||
        val key: SecretKey = SecretKeySpec(aesKey, SYM_CRYPTO_METHOD)
 | 
			
		||||
 | 
			
		||||
        val cipher = Cipher.getInstance(SYM_CRYPTO_PADDING)
 | 
			
		||||
        cipher.init(Cipher.ENCRYPT_MODE, key)
 | 
			
		||||
 | 
			
		||||
        val encryptedBytes = cipher.doFinal(mac + payload)
 | 
			
		||||
        val iv = cipher.iv
 | 
			
		||||
 | 
			
		||||
        return listOf(encryptedBytes, iv);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun symDecrypt(payload: Collection<ByteArray>, aesKey: ByteArray): ByteArray? {
 | 
			
		||||
 | 
			
		||||
        val key: SecretKey = SecretKeySpec(aesKey, SYM_CRYPTO_METHOD)
 | 
			
		||||
        val cipher = Cipher.getInstance(SYM_CRYPTO_PADDING);
 | 
			
		||||
        val iv = payload.last();
 | 
			
		||||
        val ivSpec = IvParameterSpec(iv)
 | 
			
		||||
        cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
 | 
			
		||||
 | 
			
		||||
        val decryptedBytes = cipher.doFinal(payload.first());
 | 
			
		||||
 | 
			
		||||
        val mac = decryptedBytes.copyOfRange(0, 32)
 | 
			
		||||
        val decryptedContent = decryptedBytes.copyOfRange(32, decryptedBytes.size)
 | 
			
		||||
        val verificationMac = digest(aesKey + decryptedContent)
 | 
			
		||||
 | 
			
		||||
        if (mac.contentEquals(verificationMac)) return decryptedContent
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								ios/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								ios/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
			
		||||
.idea/
 | 
			
		||||
.vagrant/
 | 
			
		||||
.sconsign.dblite
 | 
			
		||||
.svn/
 | 
			
		||||
 | 
			
		||||
.DS_Store
 | 
			
		||||
*.swp
 | 
			
		||||
profile
 | 
			
		||||
 | 
			
		||||
DerivedData/
 | 
			
		||||
build/
 | 
			
		||||
GeneratedPluginRegistrant.h
 | 
			
		||||
GeneratedPluginRegistrant.m
 | 
			
		||||
 | 
			
		||||
.generated/
 | 
			
		||||
 | 
			
		||||
*.pbxuser
 | 
			
		||||
*.mode1v3
 | 
			
		||||
*.mode2v3
 | 
			
		||||
*.perspectivev3
 | 
			
		||||
 | 
			
		||||
!default.pbxuser
 | 
			
		||||
!default.mode1v3
 | 
			
		||||
!default.mode2v3
 | 
			
		||||
!default.perspectivev3
 | 
			
		||||
 | 
			
		||||
xcuserdata
 | 
			
		||||
 | 
			
		||||
*.moved-aside
 | 
			
		||||
 | 
			
		||||
*.pyc
 | 
			
		||||
*sync/
 | 
			
		||||
Icon?
 | 
			
		||||
.tags*
 | 
			
		||||
 | 
			
		||||
/Flutter/Generated.xcconfig
 | 
			
		||||
/Flutter/flutter_export_environment.sh
 | 
			
		||||
							
								
								
									
										0
									
								
								ios/Assets/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								ios/Assets/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										4
									
								
								ios/Classes/NativeCryptoPlugin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								ios/Classes/NativeCryptoPlugin.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
#import <Flutter/Flutter.h>
 | 
			
		||||
 | 
			
		||||
@interface NativeCryptoPlugin : NSObject<FlutterPlugin>
 | 
			
		||||
@end
 | 
			
		||||
							
								
								
									
										15
									
								
								ios/Classes/NativeCryptoPlugin.m
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								ios/Classes/NativeCryptoPlugin.m
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
#import "NativeCryptoPlugin.h"
 | 
			
		||||
#if __has_include(<native_crypto/native_crypto-Swift.h>)
 | 
			
		||||
#import <native_crypto/native_crypto-Swift.h>
 | 
			
		||||
#else
 | 
			
		||||
// Support project import fallback if the generated compatibility header
 | 
			
		||||
// is not copied when this plugin is created as a library.
 | 
			
		||||
// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816
 | 
			
		||||
#import "native_crypto-Swift.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@implementation NativeCryptoPlugin
 | 
			
		||||
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
 | 
			
		||||
  [SwiftNativeCryptoPlugin registerWithRegistrar:registrar];
 | 
			
		||||
}
 | 
			
		||||
@end
 | 
			
		||||
							
								
								
									
										14
									
								
								ios/Classes/SwiftNativeCryptoPlugin.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								ios/Classes/SwiftNativeCryptoPlugin.swift
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
import Flutter
 | 
			
		||||
import UIKit
 | 
			
		||||
 | 
			
		||||
public class SwiftNativeCryptoPlugin: NSObject, FlutterPlugin {
 | 
			
		||||
  public static func register(with registrar: FlutterPluginRegistrar) {
 | 
			
		||||
    let channel = FlutterMethodChannel(name: "native_crypto", binaryMessenger: registrar.messenger())
 | 
			
		||||
    let instance = SwiftNativeCryptoPlugin()
 | 
			
		||||
    registrar.addMethodCallDelegate(instance, channel: channel)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
 | 
			
		||||
    result("iOS " + UIDevice.current.systemVersion)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								ios/native_crypto.podspec
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								ios/native_crypto.podspec
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
#
 | 
			
		||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
 | 
			
		||||
# Run `pod lib lint native_crypto.podspec' to validate before publishing.
 | 
			
		||||
#
 | 
			
		||||
Pod::Spec.new do |s|
 | 
			
		||||
  s.name             = 'native_crypto'
 | 
			
		||||
  s.version          = '0.0.1'
 | 
			
		||||
  s.summary          = 'A new flutter plugin project.'
 | 
			
		||||
  s.description      = <<-DESC
 | 
			
		||||
A new flutter plugin project.
 | 
			
		||||
                       DESC
 | 
			
		||||
  s.homepage         = 'http://example.com'
 | 
			
		||||
  s.license          = { :file => '../LICENSE' }
 | 
			
		||||
  s.author           = { 'Your Company' => 'email@example.com' }
 | 
			
		||||
  s.source           = { :path => '.' }
 | 
			
		||||
  s.source_files = 'Classes/**/*'
 | 
			
		||||
  s.dependency 'Flutter'
 | 
			
		||||
  s.platform = :ios, '8.0'
 | 
			
		||||
 | 
			
		||||
  # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported.
 | 
			
		||||
  s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
 | 
			
		||||
  s.swift_version = '5.0'
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										39
									
								
								lib/native_crypto.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								lib/native_crypto.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
			
		||||
// Copyright (c) 2020
 | 
			
		||||
// Author: Hugo Pointcheval
 | 
			
		||||
import 'dart:async';
 | 
			
		||||
import 'dart:typed_data';
 | 
			
		||||
 | 
			
		||||
import 'package:flutter/services.dart';
 | 
			
		||||
 | 
			
		||||
class NativeCrypto {
 | 
			
		||||
  static const MethodChannel _channel =
 | 
			
		||||
      const MethodChannel('native.crypto.helper');
 | 
			
		||||
 | 
			
		||||
  Future<Uint8List> sumKeygen() async {
 | 
			
		||||
    final Uint8List aesKey = await _channel.invokeMethod('symKeygen');
 | 
			
		||||
 | 
			
		||||
    return aesKey;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future<List<Uint8List>> symEncrypt(
 | 
			
		||||
      Uint8List payloadbytes, Uint8List aesKey) async {
 | 
			
		||||
    final List<Uint8List> encyptedPayload =
 | 
			
		||||
        await _channel.invokeListMethod('symEncrypt', <String, dynamic>{
 | 
			
		||||
      'payload': payloadbytes,
 | 
			
		||||
      'aesKey': aesKey,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return encyptedPayload;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future<Uint8List> symDecrypt(
 | 
			
		||||
      List<Uint8List> payloadbytes, Uint8List aesKey) async {
 | 
			
		||||
    final Uint8List decryptedPayload =
 | 
			
		||||
        await _channel.invokeMethod('symDecrypt', <String, dynamic>{
 | 
			
		||||
      'payload': payloadbytes,
 | 
			
		||||
      'aesKey': aesKey,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return decryptedPayload;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user