-1

我有两个函数用 AES-GCM 算法加密和解密数据,但使用加密包。我不认为它不好,它帮了我很多,但我想翻译它们,这样我就可以将pointycastle包用于我所有不同的加密和解密算法。

使用密码学包的功能是:

Future<CipherDataHolder> cipher(String clearValue) async {
    final algorithm = AesGcm.with256bits(nonceLength: 12); //128bits MAC default
    final SecretKey secretKey = await algorithm.newSecretKey();
    final List<int> nonce = algorithm.newNonce();

    final secretBox = await algorithm.encrypt(
      utf8.encode(clearValue),
      secretKey: secretKey,
      nonce: nonce,
    );

    String cipherText = base64.encode(secretBox.concatenation());
    String passphrase = base64.encode(await secretKey.extractBytes());
    return CipherDataHolder(ciphertext: cipherText, passphrase: passphrase);
}
Future<String> decrypt(CipherDataHolder secretData) async {
  final Uint8List cipherData = base64.decode(secretData.ciphertext);
  final Uint8List ciphertext  = cipherData.sublist(12, cipherData.length - 16);
  final Uint8List iv = cipherData.sublist(0, 12);
  final Uint8List mac = cipherData.sublist(cipherData.length - 16);

  List<int> passphrase = base64.decode(secretData.passphrase);
  final SecretKey secretKey = SecretKey(passphrase);
  final SecretBox secretBox = SecretBox(ciphertext, nonce: iv, mac: Mac(mac));
  final List<int> clearValue = await AesGcm.with256bits().decrypt(secretBox, secretKey: secretKey);

  return utf8.decode(clearValue);
}

CipherDataHolder 只是一个保存值的类

class CipherDataHolder {
  CipherDataHolder({required this.ciphertext, required this.passphrase});
  String ciphertext;
  String passphrase;
}

///////////////////////////////////////// //////////////////

更新

///////////////////////////////////////// //////////////////

这是我到目前为止尝试翻译这些功能的方法

使用 pointycastle 包的功能是:

Future<CipherDataHolder> cipherWithGCMyPointyCastle({required String clearValue}) async {
    final Uint8List key = genKey(); //32 bytes key
  final Uint8List nonce = generateRandomNonce();  //12 bytes nonce
  final List<int> plainTextBytes = utf8.encode(clearValue);

  final cipher = pointy.GCMBlockCipher(pointy.AESEngine())
    ..init(
        true, // encrypt
        pointy.AEADParameters(
          pointy.KeyParameter(key), // the 256 bit (32 byte) key
          128,  //Mac length
          nonce, // the 12 byte nonce
          Uint8List(0), // empty extra data
        ));

  //Last 16 is mac data, rest is plaintext Bytes
  Uint8List cipherTextBytes = cipher.process(Uint8List.fromList(plainTextBytes));

  //Concatenate nonce + cipherText + mac bytes
  String cipherText = base64.encode(concatenateCipherData(nonceBytes: cipher.nonce, cipherTextBytes: cipherTextBytes.sublist(0, cipherTextBytes.length - 16), macBytes: cipher.mac));
  return CipherDataHolder(ciphertext: cipherText, passphrase: base64.encode(key));
}
  Future<String> decryptWithGCMyPointyCastle(CipherDataHolder secretData) async {
      final Uint8List cipherData = base64.decode(secretData.ciphertext);
  final Uint8List ciphertext = cipherData.sublist(12, cipherData.length - 16); //Rest between 12 and last 16
  final Uint8List nonce = cipherData.sublist(0, 12); //First 12 bytes
  final Uint8List mac = cipherData.sublist(cipherData.length - 16); //last 16 bytes

  List<int> passphrase = base64.decode(secretData.passphrase);

  final cipher = pointy.GCMBlockCipher(pointy.AESEngine())
        ..init(
            false, // decrypt
            pointy.AEADParameters(
              pointy.KeyParameter(Uint8List.fromList(passphrase)),
              128,
              nonce,
              Uint8List(0),
            ));

  BytesBuilder bb = BytesBuilder();
  bb.add(ciphertext);
  bb.add(mac);
  Uint8List ciphertextWithTag = bb.toBytes();

  return String.fromCharCodes(cipher.process(ciphertextWithTag));
}

我仍然有一些疑问,我不知道我是否做对了。但是密码和解密现在正在工作,当我对数据进行加密时,我使用密码学包得到了类似的结果。

现在的主要问题是当我用pointycastle加密时,例如这个值:abc123|@#¢∞¬÷“”≠

密码学结果:abc123|@#¢∞¬÷“”≠

pointycastle 的结果:abc123|@#¢â¬÷âââ

我知道这可能是某种编码问题,但我看不出在哪里:(问题可能出在哪里或我做错了什么?

这些是辅助功能

  Uint8List concatenateCipherData({required List<int> nonceBytes, required List<int> cipherTextBytes, required List<int> macBytes}) {
    int n = cipherTextBytes.length + nonceBytes.length + macBytes.length;
    Uint8List result = Uint8List(n);

    int i = 0;
    result.setAll(i, nonceBytes);
    i += nonceBytes.length;

    result.setAll(i, cipherTextBytes);
    i += cipherTextBytes.length;

    result.setAll(i, macBytes);

    return result;
  }

  Uint8List generateRandomNonce() {
    final _sGen = Random.secure();
    final _seed = Uint8List.fromList(List.generate(32, (n) => _sGen.nextInt(256)));
    pointy.SecureRandom sec = pointy.SecureRandom("Fortuna")..seed(pointy.KeyParameter(_seed));
    return sec.nextBytes(12);
  }
  Uint8List genKey() {
    final _sGen = Random.secure();
    final _seed = Uint8List.fromList(List.generate(32, (n) => _sGen.nextInt(256)));
    pointy.SecureRandom sec = pointy.SecureRandom("Fortuna")..seed(pointy.KeyParameter(_seed));
    return sec.nextBytes(32);
  }
4

1 回答 1

1

所有 pointcastle 密码都以基本相同的方式实例化。这是实例化 AES/GCM 的方法,带有输入和输出的示例。

  final keyBytes = Uint8List(32); // dummy key - replace with 256 bit key
  final nonce = Uint8List(12); // dummy nonce - replace with random value
  final plainTextBytes = Uint8List(5); // dummy input - 5 bytes (5 is just an example)

  final cipher = GCMBlockCipher(AESEngine())
    ..init(
        true, // encrypt (or decrypt)
        AEADParameters(
          KeyParameter(keyBytes), // the 256 bit (32 byte) key
          16 * 8, // the mac size (16 bytes)
          nonce, // the 12 byte nonce
          Uint8List(0), // empty extra data
        ));

  final cipherTextBytes = cipher.process(plainTextBytes);
  print(cipherTextBytes.length); // prints 21 = 16 (mac) + 5 (plain text length) 
于 2022-01-07T01:54:09.033 回答