|
|
@@ -0,0 +1,452 @@
|
|
|
+import 'dart:convert';
|
|
|
+import 'dart:ffi';
|
|
|
+import 'dart:io';
|
|
|
+import 'dart:math';
|
|
|
+import 'dart:typed_data';
|
|
|
+import 'package:ffi/ffi.dart';
|
|
|
+import 'package:path_provider/path_provider.dart';
|
|
|
+
|
|
|
+
|
|
|
+// TODO: 让_Block的size可以设置
|
|
|
+
|
|
|
+
|
|
|
+class Block16 extends Struct {
|
|
|
+ @Array(16) external Array<Uint8> buf;
|
|
|
+}
|
|
|
+class Block32 extends Struct {
|
|
|
+ @Array(32) external Array<Uint8> buf;
|
|
|
+}
|
|
|
+
|
|
|
+extension ExBlock16 on Pointer<Block16> {
|
|
|
+ Pointer<Uint8> get p => Pointer.fromAddress(address);
|
|
|
+ Uint8List get list => p.asTypedList(16);
|
|
|
+}
|
|
|
+extension ExBlock32 on Pointer<Block32> {
|
|
|
+ Pointer<Uint8> get p => Pointer.fromAddress(address);
|
|
|
+ Uint8List get list => p.asTypedList(32);
|
|
|
+ void copy(Pointer<Block32> key) {
|
|
|
+ for (int i=0; i<32; ++i) {
|
|
|
+ key.ref.buf[i]=1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class SM2Point extends Struct {
|
|
|
+ external Block32 x, y;
|
|
|
+}
|
|
|
+
|
|
|
+extension ExSM2Point on Pointer<SM2Point> {
|
|
|
+ Pointer<Block32> get x => Pointer.fromAddress(address);
|
|
|
+ Pointer<Block32> get y => x.elementAt(1);
|
|
|
+}
|
|
|
+
|
|
|
+class Block {
|
|
|
+ Block(this.size): p = malloc.allocate(size);
|
|
|
+
|
|
|
+ final int size;
|
|
|
+ final Pointer<Uint8> p;
|
|
|
+ Uint8List get list => p.asTypedList(size);
|
|
|
+ // Pointer<Uint8> elementAt(int index) => p.elementAt(index);
|
|
|
+ // int operator[](int index) => p[index];
|
|
|
+ // void operator[]=(int index, int value) => p[index] = value;
|
|
|
+}
|
|
|
+
|
|
|
+class SM2Key extends Struct {
|
|
|
+ external SM2Point publicKey;
|
|
|
+ external Block32 privateKey;
|
|
|
+}
|
|
|
+extension ExSM2Key on Pointer<SM2Key> {
|
|
|
+ Pointer<SM2Point> get publicKey => Pointer.fromAddress(address);
|
|
|
+ Pointer<Block32> get privateKey => Pointer.fromAddress(address + 64);
|
|
|
+ void generate() {
|
|
|
+ assert(gm.sm2KeyGenerate(this) == 1);
|
|
|
+ }
|
|
|
+ void copy(Pointer<SM2Key> key) {
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+class SM4cbcCtx extends Struct {
|
|
|
+ @Array(32)
|
|
|
+ external Array<Uint32> sm4Key;
|
|
|
+ external Block16 iv, block;
|
|
|
+ @Size()
|
|
|
+ external int blockNBytes;
|
|
|
+}
|
|
|
+
|
|
|
+extension ExSM4CBCCtx on Pointer<SM4cbcCtx> {
|
|
|
+ Pointer<Uint32> get sm4Key => Pointer.fromAddress(address);
|
|
|
+ Pointer<Block16> get iv => Pointer.fromAddress(sm4Key.elementAt(32).address);
|
|
|
+ Pointer<Block16> get block => iv.elementAt(1);
|
|
|
+ int get size => ref.blockNBytes;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+final _lib = DynamicLibrary.open("libgmssl.so");
|
|
|
+final gm = GmSSL._();
|
|
|
+
|
|
|
+final stderrAddress = _lib.lookup<UintPtr>("stderr").value;
|
|
|
+
|
|
|
+
|
|
|
+final stdoutAddress = _lib.lookup<UintPtr>("stdout").value;
|
|
|
+
|
|
|
+final _fputs = _lib.lookupFunction<Int Function(Pointer<Utf8>, UintPtr),
|
|
|
+ int Function(Pointer<Utf8>, int)>("fputs");
|
|
|
+
|
|
|
+int fputs(String str, int stream) {
|
|
|
+ return _fputs(str.toNativeUtf8(), stream);
|
|
|
+}
|
|
|
+
|
|
|
+final _puts = _lib.lookupFunction<Int Function(Pointer<Utf8>),
|
|
|
+ int Function(Pointer<Utf8>)>("puts");
|
|
|
+
|
|
|
+int puts(String str) {
|
|
|
+ return _puts(str.toNativeUtf8());
|
|
|
+}
|
|
|
+
|
|
|
+final _freopen = _lib.lookupFunction<
|
|
|
+ UintPtr Function(Pointer<Utf8>, Pointer<Utf8>, UintPtr),
|
|
|
+ int Function(Pointer<Utf8>, Pointer<Utf8>, int)>("freopen");
|
|
|
+
|
|
|
+int freopen(String path, String mode, int stream) {
|
|
|
+ return _freopen(path.toNativeUtf8(), mode.toNativeUtf8(), stream);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const sm2MaxPlainText = 255;
|
|
|
+const sm2MaxCipherTextSize = 366;
|
|
|
+
|
|
|
+class GmSSL {
|
|
|
+ GmSSL._();
|
|
|
+
|
|
|
+ Pointer<SM2Key> newSM2Key() => malloc<SM2Key>();
|
|
|
+
|
|
|
+ final _fopen = _lib.lookupFunction<
|
|
|
+ UintPtr Function(Pointer<Utf8>, Pointer<Utf8>),
|
|
|
+ int Function(Pointer<Utf8>, Pointer<Utf8>)
|
|
|
+ >("fopen");
|
|
|
+ final fflush = _lib.lookupFunction<Uint32 Function(UintPtr),
|
|
|
+ int Function(int)>("fflush");
|
|
|
+ final fclose = _lib.lookupFunction<Uint32 Function(UintPtr),
|
|
|
+ int Function(int)>("fclose");
|
|
|
+
|
|
|
+ int fopen(String path, String mode) {
|
|
|
+ return _fopen(path.toNativeUtf8(), mode.toNativeUtf8());
|
|
|
+ }
|
|
|
+
|
|
|
+ final sm2KeyGenerate = _lib.lookupFunction<Int Function(Pointer<SM2Key>),
|
|
|
+ int Function(Pointer<SM2Key>)>("sm2_key_generate");
|
|
|
+ // TODO: something wrong ...
|
|
|
+ final sm2PrivateKeyInfoEncryptToDER = _lib.lookupFunction<
|
|
|
+ Int Function(SM2Key, Pointer<Utf8>, Pointer<Pointer<Uint8>>, Pointer<Size>),
|
|
|
+ int Function(SM2Key, Pointer<Utf8>, Pointer<Pointer<Uint8>>, Pointer<Size>)
|
|
|
+ >("sm2_private_key_info_encrypt_to_der");
|
|
|
+
|
|
|
+ // TODO: unimplemented ...
|
|
|
+ final sm2PrivateKeyInfoDecryptFromDER = _lib.lookupFunction<
|
|
|
+ Int Function(SM2Key, Pointer<Pointer<Uint8>>, Pointer<Size>,
|
|
|
+ Pointer<Utf8>, Pointer<Pointer<Uint8>>, Pointer<Size>),
|
|
|
+ int Function(SM2Key, Pointer<Pointer<Uint8>>, Pointer<Size>,
|
|
|
+ Pointer<Utf8>, Pointer<Pointer<Uint8>>, Pointer<Size>)
|
|
|
+ >("sm2_private_key_info_decrypt_from_der");
|
|
|
+
|
|
|
+
|
|
|
+ final sm2PrivateKeyInfoEncryptToPEM = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM2Key>, Pointer<Utf8>, UintPtr),
|
|
|
+ int Function(Pointer<SM2Key>, Pointer<Utf8>, int)
|
|
|
+ >("sm2_private_key_info_encrypt_to_pem");
|
|
|
+
|
|
|
+ final sm2PrivateKeyInfoDecryptFromPEM = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM2Key>, Pointer<Utf8>, UintPtr),
|
|
|
+ int Function(Pointer<SM2Key>, Pointer<Utf8>, int)
|
|
|
+ >("sm2_private_key_info_decrypt_from_pem");
|
|
|
+
|
|
|
+ final sm2PublicKeyInfoToPEM = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM2Key>, UintPtr), int Function(Pointer<SM2Key>, int)
|
|
|
+ >("sm2_public_key_info_to_pem");
|
|
|
+ final sm2PublicKeyInfoFromPEM = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM2Key>, UintPtr), int Function(Pointer<SM2Key>, int)
|
|
|
+ >("sm2_public_key_info_from_pem");
|
|
|
+ final sm2PublicKeyInfoToDER = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM2Key>, Pointer<UintPtr>, Pointer<Size>),
|
|
|
+ int Function(Pointer<SM2Key>, Pointer<UintPtr>, Pointer<Size>)
|
|
|
+ >("sm2_public_key_info_to_der");
|
|
|
+ final sm2PublicKeyInfoFromDER = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM2Key>, Pointer<Pointer<Uint8>>, Pointer<Size>),
|
|
|
+ int Function(Pointer<SM2Key>, Pointer<Pointer<Uint8>>, Pointer<Size>)
|
|
|
+ >("sm2_public_key_info_from_der");
|
|
|
+
|
|
|
+ final sm2Encrypt = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM2Key>, Pointer<Uint8>, Size, Pointer<Uint8>, Pointer<Size>),
|
|
|
+ int Function(Pointer<SM2Key>, Pointer<Uint8>, int, Pointer<Uint8>, Pointer<Size>)
|
|
|
+ >("sm2_encrypt");
|
|
|
+ final sm2Decrypt = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM2Key>, Pointer<Uint8>, Size, Pointer<Uint8>, Pointer<Size>),
|
|
|
+ int Function(Pointer<SM2Key>, Pointer<Uint8>, int, Pointer<Uint8>, Pointer<Size>)
|
|
|
+ >("sm2_decrypt");
|
|
|
+
|
|
|
+
|
|
|
+ final sm4cbcEncryptInit = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM4cbcCtx>, Pointer<Block16>, Pointer<Block16>),
|
|
|
+ int Function(Pointer<SM4cbcCtx>, Pointer<Block16>, Pointer<Block16>)
|
|
|
+ >("sm4_cbc_encrypt_init");
|
|
|
+ final sm4cbcEncryptUpdate = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM4cbcCtx>, Pointer<Uint8>, Size, Pointer<Uint8>, Pointer<Size>),
|
|
|
+ int Function(Pointer<SM4cbcCtx>, Pointer<Uint8>, int, Pointer<Uint8>, Pointer<Size>)
|
|
|
+ >("sm4_cbc_encrypt_update");
|
|
|
+ final sm4cbcEncryptFinish = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM4cbcCtx>, Pointer<Uint8>, Pointer<Size>),
|
|
|
+ int Function(Pointer<SM4cbcCtx>, Pointer<Uint8>, Pointer<Size>)
|
|
|
+ >("sm4_cbc_encrypt_finish");
|
|
|
+ final sm4cbcDecryptInit = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM4cbcCtx>, Pointer<Block16>, Pointer<Block16>),
|
|
|
+ int Function(Pointer<SM4cbcCtx>, Pointer<Block16>, Pointer<Block16>)
|
|
|
+ >("sm4_cbc_decrypt_init");
|
|
|
+ final sm4cbcDecryptUpdate = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM4cbcCtx>, Pointer<Uint8>, Size, Pointer<Uint8>, Pointer<Size>),
|
|
|
+ int Function(Pointer<SM4cbcCtx>, Pointer<Uint8>, int, Pointer<Uint8>, Pointer<Size>)
|
|
|
+ >("sm4_cbc_decrypt_update");
|
|
|
+ final sm4cbcDecryptFinish = _lib.lookupFunction<
|
|
|
+ Int Function(Pointer<SM4cbcCtx>, Pointer<Uint8>, Pointer<Size>),
|
|
|
+ int Function(Pointer<SM4cbcCtx>, Pointer<Uint8>, Pointer<Size>)
|
|
|
+ >("sm4_cbc_decrypt_finish");
|
|
|
+}
|
|
|
+
|
|
|
+Uint8List sm4cbcEncrypt(Uint8List input, Uint8List sm4key, Uint8List iv) {
|
|
|
+ assert(sm4key.length == 16, "key length error");
|
|
|
+ assert(iv.length == 16, "key length error");
|
|
|
+ // print("sm4cbcEncrypt start...");
|
|
|
+ // print("malloc...");
|
|
|
+ final ctx = malloc<SM4cbcCtx>();
|
|
|
+ final key = malloc<Block16>();
|
|
|
+ final civ = malloc<Block16>();
|
|
|
+ final inBuf = malloc<Uint8>(4096);
|
|
|
+ final outBuf = malloc<Uint8>(4196);
|
|
|
+ final outLen = malloc<Size>();
|
|
|
+ final output = <int>[];
|
|
|
+ // print("copy...");
|
|
|
+ for (int i=0; i<16; ++i) {
|
|
|
+ key.p[i] = sm4key[i];
|
|
|
+ }
|
|
|
+ for (int i=0; i<16; ++i) {
|
|
|
+ civ.p[i] = iv[i];
|
|
|
+ }
|
|
|
+ // print("init...");
|
|
|
+ assert(gm.sm4cbcEncryptInit(ctx, key, civ) == 1,
|
|
|
+ "sm4cbcEncryptInit error");
|
|
|
+ // print("encrypt...");
|
|
|
+ for (int i=0; i<input.length; i+=4096) {
|
|
|
+ final j = min(i+4096, input.length), len = j-i;
|
|
|
+ for (int k=i; k<j; ++k) {
|
|
|
+ inBuf[k-i] = input[k];
|
|
|
+ }
|
|
|
+ assert(gm.sm4cbcEncryptUpdate(ctx, inBuf, len, outBuf, outLen) == 1,
|
|
|
+ "sm4cbcEncryptUpdate error");
|
|
|
+ output.addAll(outBuf.asTypedList(outLen.value));
|
|
|
+
|
|
|
+ }
|
|
|
+ assert(gm.sm4cbcEncryptFinish(ctx, outBuf, outLen) == 1,
|
|
|
+ "sm4cbcEncryptFinish error");
|
|
|
+
|
|
|
+ output.addAll(outBuf.asTypedList(outLen.value));
|
|
|
+
|
|
|
+ malloc.free(ctx);
|
|
|
+ malloc.free(key);
|
|
|
+ malloc.free(civ);
|
|
|
+ malloc.free(inBuf);
|
|
|
+ malloc.free(outBuf);
|
|
|
+ malloc.free(outLen);
|
|
|
+ // print("sm4cbcEncrypt return...");
|
|
|
+ return Uint8List.fromList(output);
|
|
|
+}
|
|
|
+
|
|
|
+Uint8List sm4cbcDecrypt(Uint8List input, Uint8List sm4key, Uint8List iv) {
|
|
|
+ assert(sm4key.length == 16, "key length error");
|
|
|
+ assert(iv.length == 16, "key length error");
|
|
|
+ // print("sm4cbcDecrypt start...");
|
|
|
+ final ctx = malloc<SM4cbcCtx>();
|
|
|
+ final key = malloc<Block16>();
|
|
|
+ final civ = malloc<Block16>();
|
|
|
+ final inBuf = malloc<Uint8>(4096);
|
|
|
+ final outBuf = malloc<Uint8>(4196);
|
|
|
+ final outLen = malloc<Size>();
|
|
|
+ final output = <int>[];
|
|
|
+ for (int i=0; i<16; ++i) {
|
|
|
+ key.p[i] = sm4key[i];
|
|
|
+ }
|
|
|
+ for (int i=0; i<16; ++i) {
|
|
|
+ civ.p[i] = iv[i];
|
|
|
+ }
|
|
|
+ assert(gm.sm4cbcDecryptInit(ctx, key, civ) == 1,
|
|
|
+ "sm4cbcDecryptInit error");
|
|
|
+ for (int i=0; i<input.length; i+=4096) {
|
|
|
+ final j = min(i+4096, input.length), len = j-i;
|
|
|
+ for (int k=i; k<j; ++k) {
|
|
|
+ inBuf[k-i] = input[k];
|
|
|
+ }
|
|
|
+ assert(gm.sm4cbcDecryptUpdate(ctx, inBuf, len, outBuf, outLen) == 1,
|
|
|
+ "sm4cbcEncryptUpdate error");
|
|
|
+ output.addAll(outBuf.asTypedList(outLen.value));
|
|
|
+ }
|
|
|
+ assert(gm.sm4cbcDecryptFinish(ctx, outBuf, outLen) == 1,
|
|
|
+ "sm4cbcDecryptFinish error");
|
|
|
+
|
|
|
+ output.addAll(outBuf.asTypedList(outLen.value));
|
|
|
+
|
|
|
+ malloc.free(ctx);
|
|
|
+ malloc.free(key);
|
|
|
+ malloc.free(civ);
|
|
|
+ malloc.free(inBuf);
|
|
|
+ malloc.free(outBuf);
|
|
|
+ malloc.free(outLen);
|
|
|
+ // print("sm4cbcDecrypt return...");
|
|
|
+ return Uint8List.fromList(output);
|
|
|
+}
|
|
|
+
|
|
|
+Uint8List sm2PublicKeyInfoToDER(Pointer<SM2Key> key) {
|
|
|
+ final buf = malloc<Uint8>(512);
|
|
|
+ final p = malloc<UintPtr>(1);
|
|
|
+ p.value = buf.address;
|
|
|
+ final len = malloc<Size>(1);
|
|
|
+ len.value = 0;
|
|
|
+ assert(gm.sm2PublicKeyInfoToDER(key, p, len) == 1);
|
|
|
+ assert(len.value >= 0 && len.value < 512, "error: len.value == ${len.value}");
|
|
|
+ final res = buf.asTypedList(len.value);
|
|
|
+ malloc.free(buf);
|
|
|
+ malloc.free(len);
|
|
|
+ malloc.free(p);
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
+int sm2PublicKeyInfoFromDER(Pointer<SM2Key> key, Uint8List der) {
|
|
|
+ final buf = malloc<Uint8>(512);
|
|
|
+ final len = malloc<Size>();
|
|
|
+ len.value = der.length;
|
|
|
+ final p = malloc<Pointer<Uint8>>();
|
|
|
+ p.value = buf;
|
|
|
+ for (int i=0; i<der.length; ++i) {
|
|
|
+ buf[i] = der[i];
|
|
|
+ }
|
|
|
+ final res = gm.sm2PublicKeyInfoFromDER(key, p, len);
|
|
|
+ malloc.free(buf);
|
|
|
+ malloc.free(p);
|
|
|
+ malloc.free(len);
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
+// Future<String> get _tempPemPath async =>
|
|
|
+// "${(await getTemporaryDirectory()).path}/temp.pem";
|
|
|
+
|
|
|
+
|
|
|
+// Future<String> sm2PublicKeyInfoToPEMString(SM2Key key) async {
|
|
|
+// final path = await _tempPemPath;
|
|
|
+// final res = sm2PublicKeyInfoToPEM(key, path);
|
|
|
+// assert(res == 1);
|
|
|
+// return File(path).readAsStringSync();
|
|
|
+// }
|
|
|
+
|
|
|
+int sm2PublicKeyInfoToPEM(Pointer<SM2Key> key, String path) {
|
|
|
+ final pf = gm.fopen(path, "w");
|
|
|
+ final res = gm.sm2PublicKeyInfoToPEM(key, pf);
|
|
|
+ // TODO: 封装一个file类隐式执行fflush & fclose
|
|
|
+ gm.fflush(pf);
|
|
|
+ gm.fclose(pf);
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
+int sm2PublicKeyInfoFromPEM(Pointer<SM2Key> key, String path) {
|
|
|
+ final pf = gm.fopen(path, "r");
|
|
|
+ assert(pf != 0, "fopen $path failed");
|
|
|
+ final res = gm.sm2PublicKeyInfoFromPEM(key, pf);
|
|
|
+ gm.fflush(pf);
|
|
|
+ gm.fclose(pf);
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
+// Future<int> sm2PublicKeyInfoFromPEMString(SM2Key key, String pem) async {
|
|
|
+// final path = await _tempPemPath;
|
|
|
+// File file = File(path);
|
|
|
+// file.writeAsStringSync(pem);
|
|
|
+// return sm2PublicKeyInfoFromPEM(key, path);
|
|
|
+// }
|
|
|
+
|
|
|
+// Future<String> sm2PrivateKeyInfoEncryptToPEMString(
|
|
|
+// SM2Key key, Pointer<Utf8> pass) async {
|
|
|
+// final path = await _tempPemPath;
|
|
|
+// final res = sm2PrivateKeyInfoEncryptToPEM(key, pass, path);
|
|
|
+// return File(path).readAsStringSync();
|
|
|
+// // pf = gm.fopen(savePath, "r");
|
|
|
+// // assert(gm.sm2PrivateKeyInfoDecryptFromPEM(key, pass, pf) == 1);
|
|
|
+// }
|
|
|
+
|
|
|
+void sm2PrivateKeyInfoEncryptToPEM(Pointer<SM2Key> key, Pointer<Utf8> pass, String path) {
|
|
|
+ final pf = gm.fopen(path, "w");
|
|
|
+ assert(pf != 0, "fopen $path failed");
|
|
|
+ final res = gm.sm2PrivateKeyInfoEncryptToPEM(key, pass, pf);
|
|
|
+ gm.fflush(pf);
|
|
|
+ gm.fclose(pf);
|
|
|
+ assert(res == 1);
|
|
|
+}
|
|
|
+
|
|
|
+int sm2PrivateKeyInfoDecryptFromPEM(Pointer<SM2Key> key, Pointer<Utf8> pass, String path) {
|
|
|
+ final pf = gm.fopen(path, "r");
|
|
|
+ assert(pf != 0, "fopen $path failed");
|
|
|
+ final res = gm.sm2PrivateKeyInfoDecryptFromPEM(key, pass, pf);
|
|
|
+ gm.fflush(pf);
|
|
|
+ gm.fclose(pf);
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
+Uint8List sm2Encrypt(Pointer<SM2Key> key, Uint8List plaintext) {
|
|
|
+ final inLen = plaintext.length;
|
|
|
+ assert(inLen <= sm2MaxPlainText,
|
|
|
+ "plaintext length > $sm2MaxPlainText");
|
|
|
+ Pointer<Uint8> input = malloc(sm2MaxPlainText + 1);
|
|
|
+ Pointer<Uint8> output = malloc(sm2MaxCipherTextSize);
|
|
|
+ Pointer<Size> outLen = malloc<Size>();
|
|
|
+ for (int i=0; i<inLen; ++i) {
|
|
|
+ input[i] = plaintext[i];
|
|
|
+ }
|
|
|
+ final res = gm.sm2Encrypt(key, input, inLen, output, outLen);
|
|
|
+ assert(res == 1);
|
|
|
+ malloc.free(input);
|
|
|
+ malloc.free(output);
|
|
|
+ malloc.free(outLen);
|
|
|
+ return output.asTypedList(outLen.value);
|
|
|
+}
|
|
|
+
|
|
|
+Uint8List sm2Decrypt(Pointer<SM2Key> key, Uint8List ciphertext) {
|
|
|
+ final inLen = ciphertext.length;
|
|
|
+ assert(inLen <= sm2MaxCipherTextSize, "ciphertext length > $sm2MaxCipherTextSize");
|
|
|
+ Pointer<Uint8> input = malloc(sm2MaxCipherTextSize);
|
|
|
+ Pointer<Uint8> output = malloc(sm2MaxCipherTextSize);
|
|
|
+ Pointer<Size> outLen = malloc<Size>();
|
|
|
+ for (int i=0; i<inLen; ++i) {
|
|
|
+ input[i] = ciphertext[i];
|
|
|
+ }
|
|
|
+ final res = gm.sm2Decrypt(key, input, inLen, output, outLen);
|
|
|
+ assert(res == 1);
|
|
|
+ malloc.free(input);
|
|
|
+ malloc.free(output);
|
|
|
+ malloc.free(outLen);
|
|
|
+ return output.asTypedList(outLen.value);
|
|
|
+}
|
|
|
+
|
|
|
+Uint8List sm2PrivateKeyInfoEncryptToDER(SM2Key key, Pointer<Utf8> pass) {
|
|
|
+ // throw UnimplementedError("this method run incorrectly");
|
|
|
+ // TODO: something wrong...
|
|
|
+ // TODO: 检查使用完成后是否需要清理&释放内存
|
|
|
+ Pointer<Uint8> buf = malloc.allocate(1024 * sizeOf<Uint8>());
|
|
|
+ Pointer<Pointer<Uint8>> p = malloc.allocate(sizeOf<Pointer>());
|
|
|
+ p.value = buf;
|
|
|
+ Pointer<Size> len = calloc.allocate(sizeOf<Size>());
|
|
|
+
|
|
|
+ final res = gm.sm2PrivateKeyInfoEncryptToDER(key, pass, p, len);
|
|
|
+ assert(res == 1);
|
|
|
+ final list = buf.asTypedList(len.value);
|
|
|
+ // TODO: safety clean
|
|
|
+ malloc.free(buf);
|
|
|
+ malloc.free(p);
|
|
|
+ malloc.free(len);
|
|
|
+ return list;
|
|
|
+}
|