我是密码学领域的新手,我正在尝试在 flutter 中执行 AES 加密和解密功能,我正在使用 pointycastle (而且我不想更改包),问题是当我正在尝试解密
这是代码:
Future<String> aesEncrypt(String plainText, key, iv) async {
final convertedText = utf8.encode(plainText);
final keyBytes = base64Decode(key);
final ivbytes = base64Decode(iv);
final keyParams = KeyParameter(keyBytes);
final params = ParametersWithIV(keyParams, ivbytes);
final cipher = BlockCipher('AES/CBC')..init(true, params);
final paddedData = _padData(convertedText);
final encryptedBytes = cipher.process(paddedData);
return base64Encode(encryptedBytes);
}
Future<String> aesDecrypt(String encryptedText, key, iv) async {
final data = base64Decode(encryptedText);
final keyBytes = base64Decode(key);
final ivbytes = base64Decode(iv);
final keyParams = KeyParameter(keyBytes);
final params = ParametersWithIV(keyParams, ivbytes);
final cipher = BlockCipher('AES/CBC')..init(false, params);
final decryptedBytes = cipher.process(data);
final unpaddedData = _unpadData(decryptedBytes);
return utf8.decode(unpaddedData);
}
Uint8List _padData(Uint8List data) {
final blockSize = 16;
final padLength = blockSize - (data.length % blockSize);
final paddedData = Uint8List(data.length + padLength)..setAll(0, data);
for (int i = data.length; i < paddedData.length; i++) {
paddedData[i] = padLength;
}
return paddedData;
}
Uint8List _unpadData(Uint8List data){
final padLength = data[data.length - 1];
return Uint8List.sublistView(data, 0, data.length - padLength);
}
String generateKey(){
final random = math.Random.secure();
//Generate random key
final keyBytes = Uint8List(16);
for(int i = 0; i < keyBytes.length; i++){
keyBytes[i] = random.nextInt(256);
}
return base64Encode(keyBytes);
}
String generateIV(){
final random = math.Random.secure();
//Generate random key
final ivBytes = Uint8List(16);
for(int i = 0; i < ivBytes.length; i++){
ivBytes[i] = random.nextInt(256);
}
return base64Encode(ivBytes);
}
(保留生成密钥和 iv 功能实际上相同的事实),
错误出现在 _unpadData 函数中的
return Uint8List.sublistView(data, 0, data.length - padLength);
行
错误是:发生异常。 RangeError (RangeError (end): 无效值: 不在包含范围 0..16: -89)
有人知道为什么会发生这种情况吗?
AES/CBC(PKCS#7Padding 使用 PointyCastle 更容易实现(例如支持 PKCS#7 Padding):
import 'dart:typed_data';
import 'package:pointycastle/export.dart';
...
Uint8List crypt(bool isEncrypt, Uint8List data, Uint8List key, Uint8List iv) {
final params = ParametersWithIV<KeyParameter>(KeyParameter(key), iv);
final paddingParams = PaddedBlockCipherParameters<ParametersWithIV<KeyParameter>, Null>(params, null);
final cipher = CBCBlockCipher(AESEngine());
final paddingCipher = PaddedBlockCipherImpl(PKCS7Padding(), cipher)
..init(isEncrypt, paddingParams);
return paddingCipher.process(data);
}
使用示例:
import 'dart:convert';
...
final key = utf8.encode('01234567890123456789012345678901'); // For the real world: Use a random byte sequence as key or derive the key from a password with a KDF
final iv = utf8.encode('0987654321098765'); // For the real world: generate a random IV for each encryption and pass it with the ciphertext
final plaintext = utf8.encode('The quick brown fox jumps over the lazy dog');
final ciphertext = crypt(true, plaintext, key, iv); // encrypt
final decrypted = crypt(false, ciphertext, key, iv); // decrypt
print(base64Encode(ciphertext)); // viKpiZpMB+dBsLo6RuwKcVanKFyPHfLLxm4PlEWTAHxrPJ43KrA2y67sC6dBFsO4
print(utf8.decode(decrypted)); // The quick brown fox jumps over the lazy dog
请注意,现在应该使用经过身份验证的加密,例如GCM 模式。
此外,为了避免密钥/IV 重用,应为每次加密生成一个随机 IV(并与 IV 一起传递到解密端,通常是串联的)。这对于基于 CTR 的模式(例如 GCM)尤其重要。