| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- 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;
- }
|