我正在尝试使用 AES CBC 加密和 Python 中的 PKCS7 填充来加密一些文本,然后在 Dart (Flutter) 中对其进行解密。事实证明,package:pointycastle/paddings/pkcs7.dart
当加密文本不需要填充时会引发错误。
这是示例。在这里,我们对一些需要在 Python 中填充的文本进行编码。
import base64
import hashlib
from Crypto.Cipher import AES
from pkcs7 import PKCS7Encoder
secret_text = 'Text that requires padding'
key_text = "some_key"
key = hashlib.sha256(key_text.encode()).digest()
print('key: ', list(key))
iv = hashlib.md5("some_iv_text".encode('utf-8')).digest()
print('iv: ', list(iv))
encoder = PKCS7Encoder()
padded_text = encoder.encode(secret_text)
print('Padded text: ', padded_text.encode('utf-8'))
e = AES.new(key, AES.MODE_CBC, iv)
cipher_text = e.encrypt(padded_text.encode('utf-8'))
print(base64.b64encode(cipher_text).decode('utf-8'))
输出:
key: [149, 37, 31, 220, 159, 221, 63, 146, 231, 174, 209, 65, 254, 127, 208, 107, 42, 235, 157, 237, 182, 247, 172, 8, 231, 217, 186, 188, 126, 137, 139, 73]
iv: [205, 35, 149, 118, 23, 255, 66, 222, 206, 81, 138, 188, 169, 122, 96, 164]
Padded text: b'Text that requires padding\x06\x06\x06\x06\x06\x06'
PygLEjc1Kkjm5qtt5N9vHC0E7TAYVj4xLpsfa4cLiRs=
Process finished with exit code 0
接下来,我们在 Dart 中对其进行解密。
import 'dart:typed_data';
import 'package:encrypt/encrypt.dart';
import 'dart:convert';
import 'package:crypto/crypto.dart';
void main() {
String encryptedText = 'PygLEjc1Kkjm5qtt5N9vHC0E7TAYVj4xLpsfa4cLiRs=';
List<int> key_text = utf8.encode("some_key"); // data being hashed
List<int> key_bytes = sha256.convert(key_text).bytes;
final key = Key(Uint8List.fromList(key_bytes));
print('key: $key_bytes');
Encrypter encrypter =
Encrypter(AES(key, mode: AESMode.cbc, padding: 'PKCS7'));
String iv_text = 'some_iv_text';
Uint8List encrypted = Uint8List.fromList(base64.decode(encryptedText));
final iv_bytes = md5.convert(utf8.encode(iv_text)).bytes;
IV iv = IV(Uint8List.fromList(iv_bytes));
print('iv: $iv_bytes');
String decrypted = encrypter.decrypt(Encrypted(encrypted), iv: iv);
print(decrypted);
}
输出:
key: [149, 37, 31, 220, 159, 221, 63, 146, 231, 174, 209, 65, 254, 127, 208, 107, 42, 235, 157, 237, 182, 247, 172, 8, 231, 217, 186, 188, 126, 137, 139, 73]
iv: [205, 35, 149, 118, 23, 255, 66, 222, 206, 81, 138, 188, 169, 122, 96, 164]
Text that requires padding
Process finished with exit code 0
所以,一切正常。
让我们对不需要填充的文本做同样的事情。
import base64
import hashlib
from Crypto.Cipher import AES
from pkcs7 import PKCS7Encoder
secret_text = 'Text that does not require padding..............'
key_text = "some_key"
key = hashlib.sha256(key_text.encode()).digest()
print('key: ', list(key))
iv = hashlib.md5("some_iv_text".encode('utf-8')).digest()
print('iv: ', list(iv))
encoder = PKCS7Encoder()
padded_text = encoder.encode(secret_text)
print('Padded text: ', padded_text.encode('utf-8'))
e = AES.new(key, AES.MODE_CBC, iv)
cipher_text = e.encrypt(padded_text.encode('utf-8'))
print(base64.b64encode(cipher_text).decode('utf-8'))
输出:
key: [149, 37, 31, 220, 159, 221, 63, 146, 231, 174, 209, 65, 254, 127, 208, 107, 42, 235, 157, 237, 182, 247, 172, 8, 231, 217, 186, 188, 126, 137, 139, 73]
iv: [205, 35, 149, 118, 23, 255, 66, 222, 206, 81, 138, 188, 169, 122, 96, 164]
Padded text: b'Text that does not require padding..............'
W2Drr/UfPBTNG4fVPG0Lb/Ax3GAyvjNNx9BlrJcxc2RTNcf2BxT2lyIx1l2ktOYl
Process finished with exit code 0
使用相同的代码在 Dart 中解密:
import 'dart:typed_data';
import 'package:encrypt/encrypt.dart';
import 'dart:convert';
import 'package:crypto/crypto.dart';
void main() {
String encryptedText = 'W2Drr/UfPBTNG4fVPG0Lb/Ax3GAyvjNNx9BlrJcxc2RTNcf2BxT2lyIx1l2ktOYl';
List<int> key_text = utf8.encode("some_key"); // data being hashed
List<int> key_bytes = sha256.convert(key_text).bytes;
final key = Key(Uint8List.fromList(key_bytes));
print('key: $key_bytes');
Encrypter encrypter =
Encrypter(AES(key, mode: AESMode.cbc, padding: 'PKCS7'));
String iv_text = 'some_iv_text';
Uint8List encrypted = Uint8List.fromList(base64.decode(encryptedText));
final iv_bytes = md5.convert(utf8.encode(iv_text)).bytes;
IV iv = IV(Uint8List.fromList(iv_bytes));
print('iv: $iv_bytes');
String decrypted = encrypter.decrypt(Encrypted(encrypted), iv: iv);
print(decrypted);
}
输出:
key: [149, 37, 31, 220, 159, 221, 63, 146, 231, 174, 209, 65, 254, 127, 208, 107, 42, 235, 157, 237, 182, 247, 172, 8, 231, 217, 186, 188, 126, 137, 139, 73]
Unhandled exception:
Invalid argument(s): Invalid or corrupted pad block
#0 PKCS7Padding.padCount (package:pointycastle/paddings/pkcs7.dart:42:7)
#1 PaddedBlockCipherImpl.doFinal (package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart:112:30)
#2 PaddedBlockCipherImpl.process (package:pointycastle/padded_block_cipher/padded_block_cipher_impl.dart:74:25)
#3 AES.decrypt (package:encrypt/src/algorithms/aes.dart:63:22)
#4 Encrypter.decryptBytes (package:encrypt/src/encrypter.dart:25:17)
#5 Encrypter.decrypt (package:encrypt/src/encrypter.dart:31:17)
#6 main (package:zno_ua_mova/decypher_bug_reproduce.dart:28:32)
#7 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#8 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
iv: [205, 35, 149, 118, 23, 255, 66, 222, 206, 81, 138, 188, 169, 122, 96, 164]
Process finished with exit code 255
原来异常是由这个代码块抛出的package:pointycastle/paddings/pkcs7.dart:42:7
if (count > data.length || count == 0) {
throw ArgumentError('Invalid or corrupted pad block');
}
当解密工作(第一种情况)时,变量是:
count: 6
data.length: 16
当解密不起作用时(第二种情况),变量是:
count: 46
data.length: 16
pointycastle pkcs7 库有什么问题吗,还是我以错误的方式使用它?