Flutter加密解密插件crypto_pro_flutter的使用

Flutter加密解密插件crypto_pro_flutter的使用

描述

crypto_pro_flutter 是一个用于生成CADES-BES格式电子签名的Flutter插件,它利用了Crypto Pro的原生SDK。该插件目前仅支持Android平台,并且可以与外部密钥容器(如Rutoken)集成。私钥必须标记为可导出。

安装

Android项目配置
  1. 复制.aar库文件: 将插件中的.aar库文件从android/libs目录复制到你的项目中的android\app\libs目录。

  2. 修改build.gradle文件: 在android/app/build.gradle中添加以下配置:

    minSdkVersion 24
    
    buildTypes {
        release {
            shrinkResources false
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    
    packagingOptions {
        jniLibs {
            useLegacyPackaging = true
        }
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: '*.aar')
    }
    
  3. 创建proguard-rules.pro文件: 在android/app目录下创建proguard-rules.pro文件,并添加以下内容以防止代码混淆:

    -keep public class ru.CryptoPro.*
    

    由于.aar库文件在插件中被标记为compile-only,因此需要将其复制到项目中并作为implementation依赖项进行添加。Proguard用于防止发布版本构建时的代码混淆。

使用示例

以下是一个完整的Flutter示例应用程序,展示了如何使用crypto_pro_flutter插件进行初始化、添加PFX证书、获取已安装的证书、删除证书、签署文件和消息等操作。

import 'dart:async';
import 'dart:developer';
import 'dart:io';

import 'package:crypto_pro_flutter/crypto_pro_flutter.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool _initCSPResult = false;
  String? _errorMessage;
  final _cryptoProFlutterPlugin = CryptoProFlutter();

  [@override](/user/override)
  void initState() {
    super.initState();
    initPlatformState();
  }

  // 初始化平台状态
  Future<void> initPlatformState() async {
    final result = await Permission.bluetooth.request();
    final result2 = await Permission.bluetoothConnect.request();
    bool? initCSPResult;
    String? errorMessage;

    try {
      initCSPResult = await _cryptoProFlutterPlugin.initCSP(); // 初始化Crypto Pro CSP
    } on PlatformException {
      errorMessage = 'Failed to init providers'; // 捕获平台异常
    }

    if (!mounted) return;

    setState(() {
      if (initCSPResult != null) {
        _initCSPResult = initCSPResult;
      } else {
        _errorMessage = errorMessage;
      }
    });
  }

  // 获取资产文件路径
  Future<String> getAssetFilePath(String assetName) async {
    Directory directory = await getTemporaryDirectory();
    final tempPath = "${directory.path}/$assetName";
    ByteData data = await rootBundle.load("assets/$assetName");
    List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
    await File(tempPath).writeAsBytes(bytes);
    return tempPath;
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16.0),
            child: Column(
              children: [
                ElevatedButton(
                  onPressed: () async {
                    FilePickerResult? result = await FilePicker.platform.pickFiles();
                    if (result?.isSinglePick ?? false) {
                      final file = File(result!.files.single.path!);
                      await _cryptoProFlutterPlugin.addPfxCertificate(
                        file: file,
                        password: "11111111", // PFX文件密码
                      );
                    }
                  },
                  child: const Text(
                    "添加PFX证书",
                    textAlign: TextAlign.center,
                  ),
                ),
                ElevatedButton(
                  onPressed: () async {
                    await _cryptoProFlutterPlugin.addContainerFromExternalStorage(
                      storageName: 'Aktiv Rutoken ECP BT 1', // 外部存储名称
                      password: "11111111", // 密码
                    );
                  },
                  child: const Text(
                    "从外部存储添加证书",
                    textAlign: TextAlign.center,
                  ),
                ),
                ElevatedButton(
                  onPressed: () async {
                    // 添加根证书到信任存储
                    // final cert = await getAssetFilePath('root_unep_2024.crt');
                    // await _cryptoProFlutterPlugin.addCertificatesToTrustedStorage(paths: [cert]);
                  },
                  child: const Text(
                    "添加根证书到信任存储",
                    textAlign: TextAlign.center,
                  ),
                ),
                ElevatedButton(
                  onPressed: () async {
                    final certs = await _cryptoProFlutterPlugin.readContainerFromExternalStorage(
                      storageName: 'Aktiv Rutoken ECP 1',
                      password: '11111111',
                    );
                    print(certs); // 打印从外部存储读取的证书
                  },
                  child: const Text(
                    "从外部存储获取证书",
                    textAlign: TextAlign.center,
                  ),
                ),
                ElevatedButton(
                  onPressed: () async {
                    final list = await _cryptoProFlutterPlugin.getInstalledCertificates();
                    await _cryptoProFlutterPlugin.deleteCertificate(list.first); // 删除第一个证书
                  },
                  child: const Text("删除证书"),
                ),
                ElevatedButton(
                  onPressed: () async {
                    final list = await _cryptoProFlutterPlugin.getInstalledCertificates();
                    print(list); // 打印已安装的证书
                  },
                  child: const Text("获取已安装的证书"),
                ),
                ElevatedButton(
                  onPressed: () async {
                    FilePickerResult? result = await FilePicker.platform.pickFiles();
                    if (result?.isSinglePick ?? false) {
                      final list = await _cryptoProFlutterPlugin.getInstalledCertificates();
                      final file = File(result!.files.single.path!);
                      final sign = await _cryptoProFlutterPlugin.signFile(
                        file: file,
                        certificate: list.first,
                        password: "11111111",
                        format: CAdESFormat.BES, // 签名格式
                      );
                      log(sign); // 记录日志
                      Clipboard.setData(ClipboardData(text: sign)); // 复制签名到剪贴板
                    }
                  },
                  child: const Text("签署文件"),
                ),
                ElevatedButton(
                  onPressed: () async {
                    final list = await _cryptoProFlutterPlugin.getInstalledCertificates();
                    final sign = await _cryptoProFlutterPlugin.signMessage(
                      message: "测试", // 要签署的消息
                      isDetached: false,
                      certificate: list.first,
                      password: "11111111",
                      format: CAdESFormat.BES,
                    );
                    print(sign); // 打印签名结果
                  },
                  child: const Text("签署消息"),
                ),
                _errorMessage != null
                    ? Text(_errorMessage!)
                    : Text(
                        _initCSPResult.toString(),
                      ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter加密解密插件crypto_pro_flutter的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter加密解密插件crypto_pro_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter应用中使用crypto_pro_flutter插件进行加密和解密的示例代码。这个插件提供了一系列加密和解密功能,包括对称加密(如AES)和非对称加密(如RSA)。

首先,确保你的Flutter项目中已经添加了crypto_pro_flutter依赖。你可以在pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  crypto_pro_flutter: ^latest_version  # 请替换为最新版本号

然后运行flutter pub get来安装依赖。

对称加密(AES)示例

加密

import 'package:flutter/material.dart';
import 'package:crypto_pro_flutter/crypto_pro_flutter.dart';

void encryptData() async {
  // 初始化密钥和IV(初始化向量)
  final key = Uint8List.fromList('1234567890123456'.codeUnits); // 16字节密钥
  final iv = Uint8List.fromList('1234567890123456'.codeUnits); // 16字节IV

  // 待加密数据
  final plainText = 'Hello, Flutter!';
  final plainTextBytes = Uint8List.fromList(plainText.codeUnits);

  // 加密
  final encryptedData = await AES.encrypt(plainTextBytes, key, iv: iv);

  // 打印加密后的数据
  print('Encrypted Data: ${encryptedData.base64}');
}

解密

void decryptData() async {
  // 初始化密钥和IV(初始化向量)
  final key = Uint8List.fromList('1234567890123456'.codeUnits); // 16字节密钥
  final iv = Uint8List.fromList('1234567890123456'.codeUnits); // 16字节IV

  // 加密后的数据(从加密步骤中获取)
  final encryptedDataBase64 = '你加密后得到的Base64字符串';
  final encryptedData = Encrypted.fromBase64(encryptedDataBase64);

  // 解密
  final decryptedData = await AES.decrypt(encryptedData, key, iv: iv);

  // 打印解密后的数据
  print('Decrypted Data: ${String.fromCharCodes(decryptedData)}');
}

非对称加密(RSA)示例

生成密钥对

import 'package:flutter/material.dart';
import 'package:crypto_pro_flutter/crypto_pro_flutter.dart';

void generateKeyPair() async {
  // 生成RSA密钥对
  final keyPair = await RSA.generateKeyPair(bits: 2048);

  // 打印公钥和私钥
  print('Public Key: ${keyPair.publicKey.exportPkcs1().base64}');
  print('Private Key: ${keyPair.privateKey.exportPkcs1().base64}');
}

加密

void rsaEncryptData() async {
  // 从生成密钥对步骤中获取的公钥
  final publicKeyBase64 = '你生成的公钥的Base64字符串';
  final publicKey = RSAKeyPair.fromPkcs1(Uint8List.fromList(base64Decode(publicKeyBase64))).publicKey;

  // 待加密数据
  final plainText = 'Hello, RSA!';
  final plainTextBytes = Uint8List.fromList(plainText.codeUnits);

  // 加密
  final encryptedData = await RSA.encrypt(plainTextBytes, publicKey);

  // 打印加密后的数据
  print('Encrypted Data: ${encryptedData.base64}');
}

解密

void rsaDecryptData() async {
  // 从生成密钥对步骤中获取的私钥
  final privateKeyBase64 = '你生成的私钥的Base64字符串';
  final privateKey = RSAKeyPair.fromPkcs1(Uint8List.fromList(base64Decode(privateKeyBase64))).privateKey;

  // 加密后的数据(从RSA加密步骤中获取)
  final encryptedDataBase64 = '你RSA加密后得到的Base64字符串';
  final encryptedData = Encrypted.fromBase64(encryptedDataBase64);

  // 解密
  final decryptedData = await RSA.decrypt(encryptedData, privateKey);

  // 打印解密后的数据
  print('Decrypted Data: ${String.fromCharCodes(decryptedData)}');
}

注意:

  • 密钥管理对于安全性至关重要,不要在代码中硬编码密钥。
  • 加密和解密操作是异步的,因此需要使用asyncawait关键字。
  • 在实际应用中,应考虑密钥的存储和传输安全。

以上代码展示了如何使用crypto_pro_flutter插件进行基本的加密和解密操作。根据你的需求,你可能需要调整密钥长度、填充模式等参数。

回到顶部