为什么解密修改的AES-CBC密文失败解密?

发布于 2025-01-26 02:00:48 字数 568 浏览 4 评论 0原文

我试图熟悉加密/解密。我正在使用DENO,因为它支持Web Crypto API。

我可以使用AES-CBC加密并解密以获取原始的明文。

我现在正在做的是加密,然后手动修改密文,然后解密。我的期望是,这仍然有效,因为我了解AES-CBC不提供完整性和真实性检查。 (AES-GCM是AEAD的)

但是,当我修改密码文本并尝试解密时,它会失败,但会出现以下错误:

error: Uncaught (in promise) OperationError: Decryption failed
let deCryptedPlaintext = await window.crypto.subtle.decrypt(param, key, asByteArray);
                         ^
    at async SubtleCrypto.decrypt (deno:ext/crypto/00_crypto.js:598:29)
    at async file:///Users/me/delete/run.js:33:26

AES-CBC是否还具有完整性检查?还是为什么解密失败?

I am trying to get familiar with encryption/decryption. I am using deno as it supports the web crypto API.

I can encrypt and decrypt to get back the original plaintext using AES-CBC.

What I am now doing now is to encrypt, then manually modify the ciphertext and then decrypt. My expectation is that this would still work since I understand that AES-CBC does not provide integrity and authenticity check. (AES-GCM is the one that is AEAD)

But when I modify the cipher text and try to decrypt, it fails with the following error:

error: Uncaught (in promise) OperationError: Decryption failed
let deCryptedPlaintext = await window.crypto.subtle.decrypt(param, key, asByteArray);
                         ^
    at async SubtleCrypto.decrypt (deno:ext/crypto/00_crypto.js:598:29)
    at async file:///Users/me/delete/run.js:33:26

Does AES-CBC also have integrity checks? Or why is the decryption failing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

做个少女永远怀春 2025-02-02 02:00:48

在Deno中,我在围绕服务器和客户端加密JWT时也有类似的问题,并且由于相同的原因,无法依靠textDecoder类:

错误:操作Error:解密失败

几个小时后我玩耍并找到了一个解决方案,有点棘手,但正在做正确的工作:

解密失败:

(async ()=> {
    const textEncoder = new TextEncoder();
    const textDecoder = new TextDecoder();
    
    const rawKey = crypto.getRandomValues(new Uint8Array(16));
    
    //  we import the key that we have previously generated 
    const cryptoKey = await crypto.subtle.importKey(
        "raw",
        rawKey,
        "AES-CBC",
        true,
        ["encrypt", "decrypt"],
    );
    
    // we generate the IV
    const iv = crypto.getRandomValues(new Uint8Array(16));
    
    // here is the string we want to encrypt
    const stringToEncrypt = "foobar"
    
    // we encrypt
    const encryptedString = await crypto.subtle.encrypt(
        { name: "AES-CBC", iv: iv },
        cryptoKey,
        textEncoder.encode(stringToEncrypt),
    );
    
    // we transform the encrypted string to an UInt8Array
    const uint8ArrayEncryptedString = new Uint8Array(encryptedString);
    
    // we transform the Array to a String so we have a representation we can carry around
    const stringifiedEncryption = 
    String.fromCharCode(...uint8ArrayEncryptedString);
    
    /* now is time to decrypt again the message, so we transform the string into 
     a char array and for every iteration we transform 
     the char into a byte, so in the end we have a byte array
    */
    const stringByteArray = 
    [...stringifiedEncryption].map((v) => v.charCodeAt(0))
    
    // we transform the byte array into a Uint8Array buffer
    const stringBuffer = new Uint8Array(stringByteArray.length);
    
    // we load the buffer
    stringByteArray.forEach((v, i) => stringBuffer[i] = v)
    
    // we decrypt again
    const againDecrString = await crypto.subtle.decrypt(
        { name: "AES-CBC", iv: iv },
        cryptoKey,
        stringBuffer,
    );
    
    console.log(textDecoder.decode(againDecrString))
})()

对于某些人出于相同目的而依靠课程的人,我建议您使用此解决方案。基础实现在来回转换字符串时(在加密后我需要作为字符串)丢失了一些信息,因此解密失败了。

In Deno I had a similar issue while encrypting a jwt around server and client and could not rely on the TextDecoder class for the same reason:

error: OperationError: Decryption failed

After some hours I played around and found a solution, a bit tricky, but is doing the job right:

(async ()=> {
    const textEncoder = new TextEncoder();
    const textDecoder = new TextDecoder();
    
    const rawKey = crypto.getRandomValues(new Uint8Array(16));
    
    //  we import the key that we have previously generated 
    const cryptoKey = await crypto.subtle.importKey(
        "raw",
        rawKey,
        "AES-CBC",
        true,
        ["encrypt", "decrypt"],
    );
    
    // we generate the IV
    const iv = crypto.getRandomValues(new Uint8Array(16));
    
    // here is the string we want to encrypt
    const stringToEncrypt = "foobar"
    
    // we encrypt
    const encryptedString = await crypto.subtle.encrypt(
        { name: "AES-CBC", iv: iv },
        cryptoKey,
        textEncoder.encode(stringToEncrypt),
    );
    
    // we transform the encrypted string to an UInt8Array
    const uint8ArrayEncryptedString = new Uint8Array(encryptedString);
    
    // we transform the Array to a String so we have a representation we can carry around
    const stringifiedEncryption = 
    String.fromCharCode(...uint8ArrayEncryptedString);
    
    /* now is time to decrypt again the message, so we transform the string into 
     a char array and for every iteration we transform 
     the char into a byte, so in the end we have a byte array
    */
    const stringByteArray = 
    [...stringifiedEncryption].map((v) => v.charCodeAt(0))
    
    // we transform the byte array into a Uint8Array buffer
    const stringBuffer = new Uint8Array(stringByteArray.length);
    
    // we load the buffer
    stringByteArray.forEach((v, i) => stringBuffer[i] = v)
    
    // we decrypt again
    const againDecrString = await crypto.subtle.decrypt(
        { name: "AES-CBC", iv: iv },
        cryptoKey,
        stringBuffer,
    );
    
    console.log(textDecoder.decode(againDecrString))
})()

For some of you relying on the class for the same purpose, I suggest you to use this solution. The underlying implementation pheraps loses some information while converting back and forth the string (I needed it as string after the encryption) and so the decryption fails.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文