Flutter RSA 工具类

使用库

  encrypt: ^5.0.3
  pointycastle: ^3.9.1
  asn1lib: ^1.5.5

工具类代码

import 'package:encrypt/encrypt.dart' as ep;
import 'dart:convert';
import 'dart:typed_data';
import 'dart:math';
import 'package:pointycastle/export.dart';
import "package:asn1lib/asn1lib.dart";

class IFRsaUtil {
  static void onLaunch() async {
    ASN1ObjectIdentifier.registerFrequentNames();
  }

  static String encrypt(String message, RSAPublicKey pubKey) {
    ep.Encrypter handler = ep.Encrypter(ep.RSA(publicKey: pubKey));
    ep.Encrypted encrypted = handler.encrypt(message);
    return encrypted.base64;
  }

  static String decrypt(String base64Data, RSAPrivateKey priKey) {
    ep.Encrypter handler = ep.Encrypter(ep.RSA(privateKey: priKey));
    ep.Encrypted encrypted = ep.Encrypted.fromBase64(base64Data);
    return handler.decrypt(encrypted);
  }

  static void createRSAKeyPair() {
    final rsaKeyPair = generateRSAKeyPair();
    String pubKey = encodePublicKeyToPem(rsaKeyPair.publicKey);
    String priKey = encodePrivateKeyToPem(rsaKeyPair.privateKey);
    print("pub $pubKey\n pri $priKey");
  }

  // 从 PEM 字符串解析出 RSAPublicKey
  static RSAPublicKey parsePublicKeyFromPem(String pemString) {
    var publicKeyBytes = _extractBytesFromPem(pemString);
    var asn1Parser = ASN1Parser(publicKeyBytes);
    var sequence = asn1Parser.nextObject() as ASN1Sequence;
    var publicKeyBitString = sequence.elements[1] as ASN1BitString;
    var publicKeySequence = ASN1Parser(publicKeyBitString.stringValue as Uint8List).nextObject() as ASN1Sequence;
    var modulus = publicKeySequence.elements[0] as ASN1Integer;
    var exponent = publicKeySequence.elements[1] as ASN1Integer;

    return RSAPublicKey(modulus.valueAsBigInteger, exponent.valueAsBigInteger);
  }

  // 从 PEM 字符串解析出 RSAPrivateKey
  static RSAPrivateKey parsePrivateKeyFromPem(String pemString) {
    var privateKeyBytes = _extractBytesFromPem(pemString);
    var asn1Parser = ASN1Parser(privateKeyBytes);
    var sequence = asn1Parser.nextObject() as ASN1Sequence;
    var modulus = sequence.elements[1] as ASN1Integer;
    var privateExponent = sequence.elements[3] as ASN1Integer;
    var p = sequence.elements[4] as ASN1Integer;
    var q = sequence.elements[5] as ASN1Integer;

    return RSAPrivateKey(modulus.valueAsBigInteger, privateExponent.valueAsBigInteger, p.valueAsBigInteger, q.valueAsBigInteger);
  }

  // Helper function to extract bytes from PEM string
  static Uint8List _extractBytesFromPem(String pem) {
    // 去除前面部分
    String regex = r'-----BEGIN.*---\n';
    RegExp regExp = RegExp(regex, multiLine: false);
    RegExpMatch? m = regExp.firstMatch(pem);
    String pemKey = pem;
    if(m != null) {
      pemKey = pem.substring(m.end);
    }
    // 去除后面部分
    var endsWith = pemKey.indexOf('-----END');
    pemKey = pemKey.substring(0, endsWith).replaceAll('\n', '');
    // 解码
    return base64.decode(pemKey);
  }



  // // 生成 RSA 密钥对 (公钥和私钥)
  static AsymmetricKeyPair<RSAPublicKey, RSAPrivateKey> generateRSAKeyPair() {
    final keyGen = KeyGenerator('RSA');
    final secureRandom = _secureRandom();
    keyGen.init(ParametersWithRandom(
        RSAKeyGeneratorParameters(BigInt.parse('65537'), 2048, 64), secureRandom));
    final pair = keyGen.generateKeyPair();
    final myPublic = pair.publicKey as RSAPublicKey;
    final myPrivate = pair.privateKey as RSAPrivateKey;

    return AsymmetricKeyPair<RSAPublicKey, RSAPrivateKey>(myPublic, myPrivate);
  }

  // 初始化 SecureRandom (使用 FortunaRandom 实现)
  static SecureRandom _secureRandom() {
    final secureRandom = FortunaRandom();
    final seedSource = Random.secure(); // 使用 Dart 内置的 secure 随机数生成器
    final seeds = <int>[];
    for (int i = 0; i < 32; i++) {
      seeds.add(seedSource.nextInt(256)); // 生成 32 字节的种子
    }
    secureRandom.seed(KeyParameter(Uint8List.fromList(seeds)));
    return secureRandom;
  }

  // 将 RSAPublicKey 转换为 PEM 字符串
  static String encodePublicKeyToPem(RSAPublicKey publicKey) {
    var algorithmSeq = ASN1Sequence();
    var algorithmAsn1Seq = ASN1Sequence();
    algorithmAsn1Seq.add(ASN1ObjectIdentifier.fromName("rsaEncryption"));
    algorithmAsn1Seq.add(ASN1Null());
    algorithmSeq.add(algorithmAsn1Seq);

    var publicKeySeq = ASN1Sequence();
    publicKeySeq.add(ASN1Integer(publicKey.modulus!));
    publicKeySeq.add(ASN1Integer(publicKey.exponent!));
    var publicKeyBitString = ASN1BitString(Uint8List.fromList(publicKeySeq.encodedBytes));

    algorithmSeq.add(publicKeyBitString);
    var bytes = Uint8List.fromList(algorithmSeq.encodedBytes);
    return '''-----BEGIN PUBLIC KEY-----\n${base64.encode(bytes)}\n-----END PUBLIC KEY-----''';
  }

// 将 RSAPrivateKey 转换为 PEM 字符串
  static String encodePrivateKeyToPem(RSAPrivateKey privateKey) {
    var privateKeySeq = ASN1Sequence();
    privateKeySeq.add(ASN1Integer(BigInt.from(0))); // version
    privateKeySeq.add(ASN1Integer(privateKey.n!)); // modulus
    privateKeySeq.add(ASN1Integer(privateKey.exponent!)); // publicExponent
    privateKeySeq.add(ASN1Integer(privateKey.d!)); // privateExponent
    privateKeySeq.add(ASN1Integer(privateKey.p!)); // prime1
    privateKeySeq.add(ASN1Integer(privateKey.q!)); // prime2
    privateKeySeq
        .add(ASN1Integer(privateKey.privateExponent! % (privateKey.p! - BigInt.one))); // exponent1
    privateKeySeq
        .add(ASN1Integer(privateKey.privateExponent! % (privateKey.q! - BigInt.one))); // exponent2
    privateKeySeq.add(ASN1Integer(privateKey.q!.modInverse(privateKey.p!))); // coefficient

    var bytes = Uint8List.fromList(privateKeySeq.encodedBytes);
    return '''-----BEGIN PRIVATE KEY-----\n${base64.encode(bytes)}\n-----END PRIVATE KEY-----''';
  }
}

测试代码


import 'package:family_box_server_core/utils/if_rsa_util.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pointycastle/asymmetric/api.dart';

void main() {
  test('security', () {
    IFRsaUtil.onLaunch();
    final keyPair = IFRsaUtil.generateRSAKeyPair();

    String pubKeyString = IFRsaUtil.encodePublicKeyToPem(keyPair.publicKey);
    debugPrint("public key $pubKeyString");
    String priKeyString = IFRsaUtil.encodePrivateKeyToPem(keyPair.privateKey);
    debugPrint("private key $priKeyString");
    RSAPublicKey decodedPubKey = IFRsaUtil.parsePublicKeyFromPem(pubKeyString);
    RSAPrivateKey decodedPriKey = IFRsaUtil.parsePrivateKeyFromPem(priKeyString);
    String message = "abc123啊哦呃";
    String base64Data = IFRsaUtil.encrypt(message, decodedPubKey);
    String decrypted = IFRsaUtil.decrypt(base64Data, decodedPriKey);
    String decrypted2 = IFRsaUtil.decrypt(base64Data, keyPair.privateKey);

    assert(decrypted == message);
    assert(decrypted2 == message);

  });
}

那么多库,就没一个省心的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容