如何从 dart:encrypt 包和 crypto-js 获得相同的结果?

问题描述 投票:0回答:2

我在 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 中解密。

任何人都可以帮我解决上述解决方案中缺少的内容吗?

javascript flutter encryption encryption-asymmetric
2个回答
2
投票

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>


0
投票

感谢@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 代码可以很好地分别加密和解密。也可以用任何一种语言部分完成。

© www.soinside.com 2019 - 2024. All rights reserved.