输入数据长度必须是 AES CTR 中密码块大小的倍数

Sti*_*ick 5 aes dart flutter pointycastle

我使用 Dart 的加密包加密字符串。我加密的代码如下。

\n
String encrypt(String kelime) {\n    final key = Key.fromUtf8(\'H4WtkvK4qyehIe2kjQfH7we1xIHFK67e\'); //32 length\n    final iv = IV.fromUtf8(\'HgNRbGHbDSz9T0CC\');\n    final encrypter = Encrypter(AES(key, mode: AESMode.cbc));\n    final encrypted = encrypter.encrypt(kelime, iv: iv);\n    return encrypted.base64;\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

然后我使用相同的包解码加密数据,并收到此错误输入数据长度必须是密码块大小的倍数。经过一番研究,我了解到加密包在破译 AES 加密算法时遇到了困难。我了解到可以使用 Pointycastle 包解密加密的单词。代码如下

\n
String decryptt(String cipher) {\n\n    final key = Key.fromUtf8(\'H4WtkvK4qyehIe2kjQfH7we1xIHFK67e\');\n\n    final iv = IV.fromUtf8(\'HgNRbGHbDSz9T0CC\');\n\n    final encryptedText = Encrypted.fromUtf8(cipher);\n    final ctr = pc.CTRStreamCipher(pc.AESFastEngine())\n      ..init(false, pc.ParametersWithIV(pc.KeyParameter(key.bytes), iv.bytes));\n    Uint8List decrypted = ctr.process(encryptedText.bytes);\n\n    print(String.fromCharCodes(decrypted));\n\n    return String.fromCharCodes(decrypted);\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

当我解密用 pointycastle 加密的数据时,我得到这样的输出。

\n
\n

c\xc3\xb3\xc2\xa5\xc3\x84\xc3\x90\xc3\x92\xc3\x8b.\xc3\xa5$[~?q{.. 9

\n
\n

我加密的单词是

\n
\n

你好

\n
\n

我用的飞镖包

\n\n

Top*_*aco 6

使用 AES/CTR 和加密包解密时,我无法重现该问题。

以下带有加密和相关解密的代码在我的机器上运行良好:

final key = enc.Key.fromUtf8('H4WtkvK4qyehIe2kjQfH7we1xIHFK67e'); //32 length
final iv = enc.IV.fromUtf8('HgNRbGHbDSz9T0CC');

// Encryption
String kelime = 'The quick brown fox jumps over the lazy dog';
final encrypter = enc.Encrypter(enc.AES(key, mode: enc.AESMode.ctr, padding: null));
final encrypted = encrypter.encrypt(kelime, iv: iv);
final ciphertext = encrypted.base64;
print(ciphertext);

// Decryption
final decrypter = enc.Encrypter(enc.AES(key, mode: enc.AESMode.ctr, padding: null));
final decrypted = decrypter.decryptBytes(enc.Encrypted.fromBase64(ciphertext), iv: iv);
final decryptedData = utf8.decode(decrypted);
print(decryptedData);
Run Code Online (Sandbox Code Playgroud)

CTR是一种不需要填充的流密码模式。与大多数库不同,加密包不会隐式禁用 CTR 模式的填充,因此这必须显式发生( padding: null)。否则,使用其他库(例如PointyCastle)解密时)解密时,填充字节通常不会被删除。

请注意,在发布的代码中,您使用 CBC 模式进行加密,而不是 CTR 模式。也许您用于加密和解密的模式不匹配。

顺便说一句,静态 IV 通常是不安全的,尤其是对于 CTR(但对于测试目的来说还可以)。这里


如果上述代码中的解密块被替换为PointyCastle的解密,解密也有效:

// Decryption
final encryptedText = enc.Encrypted.fromBase64(ciphertext);
final ctr = pc.CTRStreamCipher(pc.AESFastEngine())..init(false, pc.ParametersWithIV(pc.KeyParameter(key.bytes), iv.bytes));
final decrypted = ctr.process(encryptedText.bytes);
final decryptedData = utf8.decode(decrypted);
print(decryptedData);
Run Code Online (Sandbox Code Playgroud)