首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过CryptoJS加密的微妙加密正确解密文本

如何通过CryptoJS加密的微妙加密正确解密文本
EN

Stack Overflow用户
提问于 2020-09-26 00:16:23
回答 1查看 704关注 0票数 2

我有代码加密用户的数据使用CryptoJS.AES,存储密钥,iv和加密的内容在不同的地方。它还使用存储的密钥和用户要求的iv来解密加密的内容。

我想使用微妙的加密浏览器API加密,这是完成的。

但我也想有可能解密旧数据(这是使用CryptoJS.AES加密)使用微妙的加密。

旧数据是用以下代码生成的

代码语言:javascript
复制
  var CryptoJS = require("crypto-js/core");
  CryptoJS.AES = require("crypto-js/aes");

  let encKey = generateRandomString();
  let aesEncrypted = CryptoJS.AES.encrypt(content, encKey);
  let encrypted = {
    key: aesEncrypted.key.toString(),
    iv: aesEncrypted.iv.toString(),
    content: aesEncrypted.toString()
  };

我试着把它解密如下

代码语言:javascript
复制
  let keyArrayBuffer = hexArrayToArrayBuffer(sliceArray(encrypted.key, 2));
  let decKey = await importKey(keyArrayBuffer);
  let decIv = hexArrayToArrayBuffer(sliceArray(encrypted.iv, 2));
  let encContent = stringToArrayBuffer(encrypted.content);
  let decryptedByteArray = await crypto.subtle.decrypt(
    { name: "AES-CBC", iv: decIv },
    decKey,
    encContent
  );
  let decrypted = new TextDecoder().decode(decrypted);

我在await crypto.subtle.decrypt上收到无回溯的DOMException错误

完整的复制可以在https://codesandbox.io/s/crypto-js-to-subtle-crypto-u0pgs?file=/src/index.js上找到。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-26 02:09:21

在CryptoJS代码中,键作为字符串传递。因此,它被解释为密码,从该密码与随机生成的8字节salt、32字节密钥和16字节IV一起导出,参见here。专有的(且相对不安全的) OpenSSL密钥导出函数EVP_BytesToKey用于此目的。

CryptoJS.AES.encrypt()返回一个CipherParams对象,该对象封装了各种参数,例如生成的键和作为WordArray的IV,请参见here。应用于密钥或IV WordArraytoString()将返回十六进制编码的数据。toString()应用于CipherParams对象,返回OpenSSL格式的密文,即第一个块(=前16个字节)由Salted__的ASCII码组成,然后是8字节的salt和实际密文,所有这些都是Base64编码的,请参阅here。这意味着实际的密文(在Base64解码之后)从第二个块开始。

以下代码说明了如何使用WebCrypto应用编程接口解密使用CryptoJS生成的密文

代码语言:javascript
复制
//
// CryptoJS
//
const content = "The quick brown fox jumps over the lazy dog";
const encKey = "This is my passphrase";

const aesEncrypted = CryptoJS.AES.encrypt(content, encKey);
const encrypted = {
    key: aesEncrypted.key.toString(),
    iv: aesEncrypted.iv.toString(),
    content: aesEncrypted.toString()
};

//
// WebCrypto API
// 
// https://stackoverflow.com/a/50868276
const fromHex = hexString => new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
// https://stackoverflow.com/a/41106346
const fromBase64 = base64String => Uint8Array.from(atob(base64String), c => c.charCodeAt(0));
 
async function decryptDemo(){
    
    const rawKey = fromHex(encrypted.key);
    const iv = fromHex(encrypted.iv);
    const ciphertext = fromBase64(encrypted.content).slice(16);
        
    const key = await window.crypto.subtle.importKey(           
        "raw",
        rawKey,                                                 
        "AES-CBC",
        true,
        ["encrypt", "decrypt"]
    );

    const decrypted = await window.crypto.subtle.decrypt(
        {
            name: "AES-CBC",
            iv: iv
        },
        key,
        ciphertext
    );

    const decoder = new TextDecoder();
    const plaintext = decoder.decode(decrypted);
    console.log(plaintext);     
}
    
decryptDemo();
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64067812

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档