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

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

自己添加pointycastle: ^3.9.1库

config.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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值