前言

FlutterUtilCode 是一个 Flutter 东西类集合插件,封装了常用的东西类函数,便利开发者调用。

本篇是 Flutter东西篇之EncryptUtils,系列文章内容首要介绍插件中东西类的功能、用法和代码完结等,感兴趣的同学能够持续重视。

FlutterUtilCode 系列(七)—— Flutter东西篇之EncryptUtils

FlutterUtilCode 系列(六)—— Flutter东西篇之AppUtils

FlutterUtilCode 系列(五)—— Flutter东西篇之PathUtils

FlutterUtilCode 系列(四)—— Flutter东西篇之DeviceUtils

FlutterUtilCode 系列(三)—— Flutter东西篇之UuidUtils

FlutterUtilCode 系列(二)—— Flutter东西篇之ToastUtils

FlutterUtilCode 系列(一)—— Flutter东西篇之LogUtils、SharedPerfsUtils

加密东西类-EncryptUtils

数据加密在 App 开发中广泛运用,其不只能够有效维护用户隐私和数据安全,还能够进步运用程序的安全性和可靠性。以下是数据加密在 App 中的常用场景:

  1. 用户密码加密:将用户密码进行哈希或者加密,以确保用户的登录信息安全。
  2. 网络传输加密:运用SSL/TLS等协议对运用程序与服务器之间的通讯进行加密,以避免网络偷听和歹意进犯。
  3. 本地存储加密:对运用程序中触及用户隐私的本地存储数据进行加密,例如付出信息、地理位置等。
  4. 运用程序代码维护:运用剧烈数据加密对运用程序代码和资源文件进行维护,以避免反编译和篡改操作。
  5. 加密算法选择:在运用程序中选择适合的加密算法,如AES加密、RSA加密、HMAC音讯认证等。
  6. 数字签名验证:运用数字签名来验证运用程序的合法性和完整性,以避免被植入歹意代码或者篡改。

在整个计算机范畴,数据加密的算法十分多,但是在 App 中一般只会用到常见的几种。今天咱们的加密东西类 EncryptUtils 将会完结以下常用的加密算法:MD5RC4AESRSASHA256withRSAMD5withRSA

一、代码完结

1.1 MD5

MD5(Message Digest Algorithm 5) 是一种常见的哈希函数,可将任意长度的音讯压缩为一个128位的摘要(Digest),通常用于数据完整性校验、数字签名等场景。

对于 MD5 加密,这儿用到了 crypto 插件。经过将字符串转换成 Uint8List ,让 crypto 完结 MD5 的转换。代码如下:

  /// MD5加密
  /// [content] 加密内容
  static String md5Encrypt(String content) {
    Uint8List uint8list = const Utf8Encoder().convert(content);
    Digest digest = md5.convert(uint8list);
    return digest.toString();
  }
1.2 RC4

RC4(Rivest Cipher 4) 是一种流密码(Stream Cipher),由Ron Rivest在1987年规划。它基于伪随机数生成器(Pseudo-Random Number Generator,PRNG)发生的密钥流来对明文进行加/解密。

因为现在没有找到有对应的插件,这儿咱们自己完结 RC4 加密算法。

第一步,生成加密 key

final Uint8List _s = Uint8List(256);
  int _i = 0;
  int _j = 0;
  void setKey(Uint8List key) {
    for (int i = 0; i < 256; i++) {
      _s[i] = i;
    }
    int j = 0;
    for (int i = 0; i < 256; i++) {
      j = (j + _s[i] + key[i % key.length]) % 256;
      swap(i, j);
    }
    _i = 0;
    _j = 0;
  }
  void swap(int i, int j) {
    int temp = _s[i];
    _s[i] = _s[j];
    _s[j] = temp;
  }

第二步,对内容进行加密,取 datakey异或运算为成果。

  /// 加密
  /// [data]数据
  Uint8List crypt(Uint8List data) {
    Uint8List result = Uint8List(data.length);
    for (int k = 0; k < data.length; k++) {
      result[k] = data[k] ^ next();
    }
    return result;
  }
  int next() {
    _i = (_i + 1) % 256;
    _j = (_j + _s[_i]) % 256;
    swap(_i, _j);
    return _s[(_s[_i] + _s[_j]) % 256];
  }

第三步,运用定义的 RC4 目标进行加密

  /// RC4加密
  /// [content] 明文
  static String rc4Encrypt(String content, String keyStr) {
    RC4 rc4 = RC4(keyStr);
    Uint8List data = Uint8List.fromList(content.codeUnits);
    Uint8List crypt = rc4.crypt(data);
    return base64Encode(crypt);
  }

第四步,运用定义的 RC4 目标进行解密

  /// RC4解密
  /// [content] 密文
  static String rc4Decrypt(String content, String keyStr) {
    RC4 rc4 = RC4(keyStr);
    Uint8List data = base64Decode(content);
    Uint8List crypt = rc4.crypt(data);
    return utf8.decode(crypt);
  }
1.3 AES

AES(Advanced Encryption Standard) 是一种高级加密标准,是现在最常用的对称加密算法之一,被广泛运用于数据维护、网络安全等范畴。它支持三个密钥长度:128位、192位和256位,其间128位密钥是最常用的。

这儿咱们运用 encrypt 插件来完结 AES 加密/解密。

  1. AES加密,默许[AESMode.ecb]加密方法
  /// AES加密, 默许[AESMode.ecb]加密方法
  /// [content] 明文
  /// [aesKey] 秘钥
  static aesEncrypt(String content, String keyStr, [AESModeType type = AESModeType.ecb]) {
    final key = Key.fromUtf8(keyStr);
    final iv = IV.fromLength(16);
    AESMode mode = AESMode.values.firstWhere((element) => element.name == type.name, orElse: () => AESMode.ecb);
    final encryptor = Encrypter(AES(key, mode: mode));
    final encrypted = encryptor.encrypt(content, iv: iv);
    return encrypted.base64;
  }
  1. AES解密,默许[AESMode.ecb]加密方法
  /// AES解密, 默许[AESMode.ecb]加密方法
  /// [content] 密文
  /// [aesKey] 秘钥
  static aesDecrypt(String content, String keyStr, [AESModeType type = AESModeType.ecb]) {
    final key = Key.fromUtf8(keyStr);
    final iv = IV.fromLength(16);
    AESMode mode = AESMode.values.firstWhere((element) => element.name == type.name, orElse: () => AESMode.ecb);
    final encryptor = Encrypter(AES(key, mode: mode));
    final encrypted = Encrypted.fromBase64(content);
    final decrypted = encryptor.decrypt(encrypted, iv: iv);
    return decrypted;
  }
1.4 RSA

RSA(Rivest-Shamir-Adleman) 是一种非对称加密算法,广泛用于数据加密和数字签名。

这儿咱们相同运用 encrypt 插件来完结 RSA 加密/解密。

  1. RSA加密,密钥格局为[pkcs8]
  /// RSA加密算法加密,秘钥格局为[pkcs8]
  /// [content]明文
  /// [publicKeyStr]公钥
  static String rsaEncrypt(String content, String publicKeyStr) {
    final parser = RSAKeyParser();
    String publicKeyString = _transformPem(publicKeyStr);
    RSAPublicKey publicKey = parser.parse(publicKeyString) as RSAPublicKey;
    final encryptor = Encrypter(RSA(publicKey: publicKey));
    final encrypted = encryptor.encrypt(content);
    return encrypted.base64;
  }
  1. RSA解密,密钥格局为[pkcs8]
  /// RSA加密算法解密,秘钥格局为[pkcs8]
  /// [encryptedStr]密文,base64编码
  /// [privateKeyStr]私钥
  static String rsaDecrypt(String encryptedStr, String privateKeyStr) {
    final parser = RSAKeyParser();
    String publicKeyString = _transformPem(privateKeyStr, isPublic: false);
    RSAPrivateKey privateKey = parser.parse(publicKeyString) as RSAPrivateKey;
    final encryptor = Encrypter(RSA(privateKey: privateKey));
    final encrypted = Encrypted.fromBase64(encryptedStr);
    final decrypted = encryptor.decrypt(encrypted);
    return decrypted;
  }
1.5 SHA256withRSA

SHA256withRSA 是一种签名算法,结合了 SHA-256哈希函数RSA非对称加密算法。它用于生成数字签名,并验证数字签名的完整性和真实性。

  1. SHA256withRSA签名,密钥格局为[pkcs8]
  /// sha256withRSA签名,秘钥格局为[pkcs8]
  /// [content]明文
  /// [privateKeyStr]私钥
  static String sha256withRSASign(String content, String privateKeyStr) {
    RSAKeyParser parser = RSAKeyParser();
    Signer signer;
    // 初始化私钥
    String privateKeyString = _transformPem(privateKeyStr, isPublic: false);
    RSAPrivateKey privateKey = parser.parse(privateKeyString) as RSAPrivateKey;
    signer = Signer(RSASigner(RSASignDigest.SHA256, privateKey: privateKey));
    var sign = signer.sign(content).base64;
    return sign;
  }
  1. SHA256withRSA验签,密钥格局为[pkcs8]
  /// sha256withRSA验签,秘钥格局为[pkcs8]
  /// [content]明文
  /// [signature]签名
  /// [publicKeyStr]公钥
  static bool sha256withRSAVerify(String content, String signature, String publicKeyStr) {
    RSAKeyParser parser = RSAKeyParser();
    Signer signer;
    // 初始化公钥
    String publicKeyString = _transformPem(publicKeyStr);
    RSAPublicKey publicKey = parser.parse(publicKeyString) as RSAPublicKey;
    signer = Signer(RSASigner(RSASignDigest.SHA256, publicKey: publicKey));
    // 验签
    var verify = signer.verify(content, Encrypted.from64(signature));
    return verify;
  }
1.6 MD5withRSA

MD5withRSA 与 SHA256withRSA 类似,也是一种签名算法,不同之处在于其是 MD5哈希函数RSA非对称加密算法 结合。相同用于生成数字签名,并验证数字签名的完整性和真实性。

这儿咱们运用 fast_rsa 插件来完结 MD5withRSA 签名

  1. MD5withRSA签名,密钥格局为[pkcs8]
  /// md5withRSA签名,秘钥格局为[pkcs8]
  /// [content]明文
  /// [privateKeyStr]私钥
  static Future<String> md5withRSASign(String content, String privateKeyStr) async {
    // 初始化私钥
    String privateKeyString = _transformPem(privateKeyStr, isPublic: false);
    String privateKey = await fast_rsa.RSA.convertPrivateKeyToPKCS1(privateKeyString);
    var sign = await fast_rsa.RSA.signPKCS1v15(content, fast_rsa.Hash.MD5, privateKey);
    return sign;
  }
  1. MD5withRSA验签,密钥格局为[pkcs8]
 /// md5withRSA验签,秘钥格局为[pkcs8]
  /// [content]明文
  /// [signature]签名
  /// [publicKeyStr]公钥
  static Future<bool> md5withRSAVerify(String content, String signature, String publicKeyStr) async {
    // 初始化公钥
    String publicKeyString = _transformPem(publicKeyStr);
    String publicKey = await fast_rsa.RSA.convertPublicKeyToPKCS1(publicKeyString);
    var verify = await fast_rsa.RSA.verifyPKCS1v15(signature, content, fast_rsa.Hash.MD5, publicKey);
    return verify;
  }

二、运用事例

EncryptUtils 的运用也是十分简略,一行代码调用即可:

// MD5加密
String md5 = EncryptUtils.md5Encrypt(content);
// RC4加密/解密
String encrypt = EncryptUtils.rc4Encrypt(content, rc4Key);
String decrypt = EncryptUtils.rc4Decrypt(encrypt, rc4Key);
// AES加密/解密
String encrypt = EncryptUtils.aesEncrypt(content, aesKey);
String decrypt = EncryptUtils.aesDecrypt(encrypt, aesKey);
// RSA加密/解密
String encrypt = EncryptUtils.rsaEncrypt(content, publicKey);
String decrypt = EncryptUtils.rsaDecrypt(encrypt, privateKey);
// SHA256withRSA 签名/验签
String sign = EncryptUtils.sha256withRSASign(content, privateKey);
bool verify = EncryptUtils.sha256withRSAVerify(content, sign, publicKey);
// MD5withRSA 签名/验签
String sign = await EncryptUtils.md5withRSASign(content, privateKey);
bool verify = await EncryptUtils.md5withRSAVerify(content, sign, publicKey);

运行成果 :

【FlutterUtilCode】Flutter工具篇之EncryptUtils

三、测试用例

测试用例 encrypt_test :

// MD5加密
test('MD5', () {
  String md5 = EncryptUtils.md5Encrypt(content);
  expect(md5, 'fc3ff98e8c6a0d3087d515c0473f8677');
});
// RC4加密/解密
test('RC4', () {
  String encrypt = EncryptUtils.rc4Encrypt(content, rc4Key);
  String decrypt = EncryptUtils.rc4Decrypt(encrypt, rc4Key);
  expect(encrypt, 'YrlMGzqCagCj9+ff');
  expect(decrypt, content);
});
// AES加密/解密
test('AES', () {
  String encrypt = EncryptUtils.aesEncrypt(content, aesKey);
  String decrypt = EncryptUtils.aesDecrypt(encrypt, aesKey);
  expect(encrypt, 'XkxSOtpoErJzTyW5/6sGNA==');
  expect(decrypt, content);
});
// RSA加密/解密
test('RSA', () async {
  String encrypt = EncryptUtils.rsaEncrypt(content, publicKey);
  String decrypt = EncryptUtils.rsaDecrypt(encrypt, privateKey);
  debugPrint('encrypt: $encrypt');
  expect(decrypt, content);
});
// SHA256withRSA 签名/验签
test('SHA256withRSA', () {
  String sign = EncryptUtils.sha256withRSASign(content, privateKey);
  bool verify = EncryptUtils.sha256withRSAVerify(content, sign, publicKey);
  debugPrint('sign: $sign');
  expect(verify, true);
});
// MD5withRSA 签名/验签
// 若呈现库无法找到问题,需要将example项目下的build文件拷贝到根目录下
test('MD5withRSA', () async {
  String sign = await EncryptUtils.md5withRSASign(content, privateKey);
  bool verify = await EncryptUtils.md5withRSAVerify(content, sign, publicKey);
  debugPrint('sign: $sign');
  expect(verify, true);
});

运行成果:

【FlutterUtilCode】Flutter工具篇之EncryptUtils

结语

好了,今天的东西类收拾文章就到这儿,现在插件已发布到 Pub 中,欢迎我们体会。

假如觉得这篇文章对你有所协助的话,不要忘记一键三连哦,我们的点赞是我更新的动力。

Pub: flutter_util_code

项目源码:FlutterUtilCode

运用事例:Example