我在 flutter 中使用
dart > encrypt
包。
我想在 flutter-web 项目的 web-worker 中做一些加密解密逻辑。我尝试使用 crypto-js
包及其普通 JS https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js.
我想验证结果是否使用相同的密钥出现相同的加密和解密值。
我也在 stackoverflow 中浏览了一些解决方案,但找不到合适的工作可以为我提供相同的生成值。
以下是 dart 代码及其结果:
import 'package:encrypt/encrypt.dart';
.
.
final key = Key.fromUtf8("VishnuTestKeyIsHereLongValid32Ch");
final encrypter = Encrypter(AES(key));
final iv = IV.fromLength(16);
var encrypted = encrypter.encrypt("Vishnu", iv: iv);
print(encrypted.base64); // prints 8beisXeeEE055QEPq+kumw==
我期望从 Crypto-js 中解密出相同的值。 https://jsfiddle.net/vcgupta/grkexuwz/4/
//html:
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
//js:
var base64Decrypted = '8beisXeeEE055QEPq+kumw=='
var myKey = "VishnuTestKeyIsHereLongValid32Ch"
var result = CryptoJS.AES.decrypt(base64Decrypted, myKey).toString(CryptoJS.enc.Utf8)
console.log(result);
我想要进行相同的操作。在 javascript 中加密并在 dart 中解密。
任何人都可以帮我解决上述解决方案中缺少的内容吗?
Dart/encrypt 默认使用 CTR 模式(又名 SIC)和 PKCS7 填充(即,流密码模式不会隐式禁用填充)。由于您没有在 CryptoJS 代码中指定模式,因此将应用默认模式,即 CBC(见here)。因此这两个代码是不兼容的。
此外,在 CryptoJS 代码中,密钥必须作为 WordArray 传递(如果作为字符串传递,则使用内置密钥派生)。此外,IV 必须显式 传递(作为 WordArray)。在 Dart 代码中,应用了零 IV(16 个 0x00 值)。
此外,您应该使用较新版本的 CryptoJS(您运行的是 3.1.2,当前版本是 4.1.1)。
总的来说,用 CryptoJS 解密是:
var base64Decrypted = '8beisXeeEE055QEPq+kumw=='
var myKey = "VishnuTestKeyIsHereLongValid32Ch"
var result = CryptoJS.AES.decrypt(
base64Decrypted,
CryptoJS.enc.Utf8.parse(myKey),
{
iv: CryptoJS.enc.Utf8.parse("\0".repeat(16)), // pass IV
mode: CryptoJS.mode.CTR, // apply CTR (aka SIC)
padding: CryptoJS.pad.Pkcs7 // apply PKCS#7 (CryptoJS default)
}
);
console.log(result.toString()); // 566973686e75 // padding removed
console.log(result.toString(CryptoJS.enc.Utf8)); // Vishnu // Utf-8 decoded
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
请记住,静态 IV(如零 IV)是一个漏洞。相反,每次加密都应该使用随机 IV,它与密文一起传递到解密方,通常是串联的(IV 不是秘密的)。
编辑:由于评论中提到的错误:测试长度超过1块(16字节)的明文:
var base64Decrypted = '87a0+WiecyRYz2l3zpRKsWHZyfUbnZ5Ar3nzYokfuD3zN7iV0M2TefRJe4pr4hh+' // from Dart
var myKey = 'VishnuTestKeyIsHereLongValid32Ch'
var result = CryptoJS.AES.decrypt(
base64Decrypted,
CryptoJS.enc.Utf8.parse(myKey),
{
iv: CryptoJS.enc.Utf8.parse('\0'.repeat(16)), // pass IV
mode: CryptoJS.mode.CTR, // apply CTR (aka SIC)
padding: CryptoJS.pad.Pkcs7 // apply PKCS#7 (CryptoJS default)
}
);
console.log(result.toString()); // 566973686e75 // padding removed
console.log(result.toString(CryptoJS.enc.Utf8)); // Vishnu // Utf-8 decoded
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
感谢@Topaco,他的解决方案非常有效。
这里有一个兼容
javascript <-> dart
的加密解密方案。希望对其他人有帮助。
var textToDecrypt = 'Some long test here';
var myKey = "VishnuTestKeyIsHereLongValid32Ch"
var result = CryptoJS.AES.encrypt(
textToDecrypt,
CryptoJS.enc.Utf8.parse(myKey),
{
iv: CryptoJS.enc. Utf8.parse("\0".repeat(16)),
mode: CryptoJS.mode.CTR,
padding: CryptoJS.pad.Pkcs7
}
);
var encryptedString = result.toString();
console.log(encryptedString);
result = CryptoJS.AES.decrypt(
encryptedString,
CryptoJS.enc.Utf8.parse(myKey),
{
iv: CryptoJS.enc. Utf8.parse("\0".repeat(16)),
mode: CryptoJS.mode.CTR,
padding: CryptoJS.pad.Pkcs7
}
);
var decryptedString = result.toString(CryptoJS.enc.Utf8);
console.log(decryptedString);
console.log(decryptedString == textToDecrypt);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
以上代码在JS中完美加密和解密。下面的代码在 dart 中具有相同的目的:
var textToDecrypt = 'Some long test here';
var myKey = "VishnuTestKeyIsHereLongValid32Ch";
final encrypter = Encrypter(AES(Key.fromUtf8(myKey)));
final iv = IV.fromLength(16);
var encrypted = encrypter.encrypt(textToDecrypt, iv: iv);
var encryptedString = encrypted.base64;
print(encryptedString);
var decrypted = encrypter.decrypt64(encryptedString, iv: iv);
var decryptedString = decrypted.toString();
print(decryptedString == ContentType.text);
dart 代码可以很好地分别加密和解密。也可以用任何一种语言部分完成。