基于最新版的flutter pointycastle: ^3.9.1的AES加密

基于最新版的flutter pointycastle: ^3.9.1的AES加密

自己添加pointycastle: ^3.9.1库

config.dart

dart 复制代码
import 'dart:convert';
import 'dart:typed_data';


class Config {
  static String password = '成都推理计算科技'; // 16字节(128位)的AES密钥
  static Uint8List iv = Uint8List.fromList([
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00
  ]); // 初始化向量(IV),对于AES/CBC/PKCS7Padding是必需的。自己按照ASCII表填点对自己有用的
  static int aesSize = 128;//可以填128,192,256
  static String aesSalt=latin1.decode([10, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);//salt可以用库里面的函数生成
}

aes_encrypt.dart

dart 复制代码
import 'dart:convert';
import 'dart:typed_data';

import 'package:pointycastle/pointycastle.dart';
import 'package:pointycastle/src/platform_check/platform_check.dart';
import 'config.dart';

class AesEncrypt {
  final iv = Config.iv;
  final password = Config.password;
  final aesSize = Config.aesSize;
  final aesSalt = Config.aesSalt;

  AesEncrypt();

  Uint8List aesCbcEncrypt(Uint8List key, Uint8List iv, Uint8List paddedPlaintext) {
    if (![128, 192, 256].contains(key.length * 8)) {
      throw ArgumentError.value(key, 'key', 'invalid key length for AES');
    }
    if (iv.length * 8 != 128) {
      throw ArgumentError.value(iv, 'iv', 'invalid IV length for AES');
    }
    if (paddedPlaintext.length * 8 % 128 != 0) {
      throw ArgumentError.value(paddedPlaintext, 'paddedPlaintext', 'invalid length for AES');
    }

    final cbc = BlockCipher('AES/CBC')..init(true, ParametersWithIV(KeyParameter(key), iv)); // true=encrypt

    final cipherText = Uint8List(paddedPlaintext.length); // allocate space

    var offset = 0;
    while (offset < paddedPlaintext.length) {
      offset += cbc.processBlock(paddedPlaintext, offset, cipherText, offset);
    }
    assert(offset == paddedPlaintext.length);

    return cipherText;
  }



  Uint8List aesCbcDecrypt(Uint8List key, Uint8List iv, Uint8List cipherText) {
    if (![128, 192, 256].contains(key.length * 8)) {
      throw ArgumentError.value(key, 'key', 'invalid key length for AES');
    }
    if (iv.length * 8 != 128) {
      throw ArgumentError.value(iv, 'iv', 'invalid IV length for AES');
    }
    if (cipherText.length * 8 % 128 != 0) {
      throw ArgumentError.value(cipherText, 'cipherText', 'invalid length for AES');
    }

    final cbc = BlockCipher('AES/CBC')..init(false, ParametersWithIV(KeyParameter(key), iv)); // false=decrypt

    final paddedPlainText = Uint8List(cipherText.length); // allocate space

    var offset = 0;
    while (offset < cipherText.length) {
      offset += cbc.processBlock(cipherText, offset, paddedPlainText, offset);
    }
    assert(offset == cipherText.length);

    return paddedPlainText;
  }


  String bin2hex(Uint8List bytes, {String? separator, int? wrap}) {
    var len = 0;
    final buf = StringBuffer();
    for (final b in bytes) {
      final s = b.toRadixString(16);
      if (buf.isNotEmpty && separator != null) {
        buf.write(separator);
        len += separator.length;
      }

      if (wrap != null && wrap < len + 2) {
        buf.write('\n');
        len = 0;
      }

      buf.write('${(s.length == 1) ? '0' : ''}$s');
      len += 2;
    }
    return buf.toString();
  }

  Uint8List hex2bin(String hexStr) {
    if (hexStr.length % 2 != 0) {
      throw const FormatException('not an even number of hexadecimal characters');
    }
    final result = Uint8List(hexStr.length ~/ 2);
    for (var i = 0; i < result.length; i++) {
      result[i] = int.parse(hexStr.substring(2 * i, 2 * (i + 1)), radix: 16);
    }
    return result;
  }

  Uint8List pad(Uint8List bytes, int blockSizeBytes) {
    final padLength = blockSizeBytes - (bytes.length % blockSizeBytes);

    final padded = Uint8List(bytes.length + padLength)..setAll(0, bytes);
    Padding('PKCS7').addPadding(padded, bytes.length);

    return padded;
  }



  Uint8List unpad(Uint8List padded) => padded.sublist(0, padded.length - Padding('PKCS7').padCount(padded));

  Uint8List passphraseToKey(String passPhrase, {String salt = '', int iterations = 30000, required int bitLength}) {
    if (![128, 192, 256].contains(bitLength)) {
      throw ArgumentError.value(bitLength, 'bitLength', 'invalid for AES');
    }
    final numBytes = bitLength ~/ 8;

    final kd = KeyDerivator('SHA-256/HMAC/PBKDF2')..init(Pbkdf2Parameters(utf8.encode(salt), iterations, numBytes));

    return kd.process(utf8.encode(passPhrase));
  }

  Uint8List? generateRandomBytes(int numBytes) {
    if (_secureRandom == null) {
      // First invocation: create _secureRandom and seed it
      _secureRandom = SecureRandom('Fortuna');
      _secureRandom!.seed(KeyParameter(Platform.instance.platformEntropySource().getBytes(32)));
    }

    // Use it to generate the random bytes

    final iv = _secureRandom!.nextBytes(numBytes);
    return iv;
  }

  SecureRandom? _secureRandom;

  Uint8List encrypt(String textToEncrypt) {
    final cipherText = aesCbcEncrypt(
        passphraseToKey(password, salt: aesSalt, bitLength: aesSize), iv, pad(utf8.encode(textToEncrypt), 16));
    return cipherText;
  }

  String decrypt(List<int> cipherListInt) {
    Uint8List cipherText = Uint8List.fromList(cipherListInt);
    final paddedDecryptedBytes =
        aesCbcDecrypt(passphraseToKey(password, salt: aesSalt, bitLength: aesSize), iv, cipherText);
    final decryptedBytes = unpad(paddedDecryptedBytes);
    final decryptedText = utf8.decode(decryptedBytes);
    return decryptedText;
  }
}
相关推荐
索迪迈科技28 分钟前
java后端工程师进修ing(研一版‖day42)
java·开发语言·学习·算法
Chris.Yuan7701 小时前
Java代理模式详解
java·开发语言·代理模式
Forever_Hopeful1 小时前
【C 语言生成指定范围随机数(整数 + 小数):原理、实现与避坑指南】
服务器·c语言·开发语言
午夜游鱼1 小时前
Go 泛型实战:一行代码封装 sync.Pool,性能与安全兼得
开发语言·安全·golang
索迪迈科技2 小时前
STL库——map/set(类函数学习)
开发语言·c++·学习
ForteScarlet2 小时前
Kotlin 2.2.20 现已发布!下个版本的特性抢先看!
android·开发语言·kotlin·jetbrains
anlogic2 小时前
Java基础 9.10
java·开发语言·算法
yongche_shi2 小时前
第二篇:Python“装包”与“拆包”的艺术:可迭代对象、迭代器、生成器
开发语言·python·面试·面试宝典·生成器·拆包·装包
Elastic 中国社区官方博客3 小时前
介绍 Python Elasticsearch Client 的 ES|QL 查询构建器
大数据·开发语言·数据库·python·elasticsearch·搜索引擎·全文检索
Hóng xīng qiáo3 小时前
swVBA自学笔记014、Lisp适合对SolidWorks进行二次开发吗 ?
开发语言·笔记·lisp