JavaScript解密AES-GCM不起作用,但在Python中起作用

发布于 2025-01-17 10:04:37 字数 4567 浏览 1 评论 0原文

我想将一个小型 python 库移植到 JavaScript,在 Node.JS 中运行。 我收到一条加密消息、初始化向量和密钥。

在 python3 中,这些是导入:

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from binascii import unhexlify
import sys
import string
from Cryptodome.Cipher import AES

解密的工作原理如下:

frame = unhexlify(frame)
encryption_key = unhexlify(str_key)
init_vector = unhexlify(str_iv)
cipher = AES.new(encryption_key, AES.MODE_GCM, nonce=init_vector)
decrypted_msg = cipher.decrypt(frame).hex()    

密钥是一个十六进制字符串,如下所示(示例): 36C66639E48A8CA4D6BC8B282A793BBB

IV 是这样的(示例): 4B464D675000000900000023

消息如下: 88D5AB4F97515AAFC6B88D2F85DAA7A0E3C0C40D004535C397C9D037AB7DBDA329107615444894A1A0DD7E85F02D496CECD3FF46AF5FB3C9229CFE8F3EE4 606AB2E1F409F36AAD2E50900A4396FC6C2E083F373233A69616950758BFC7D63 A9E9B6E99E21B2CBC2B934772CA51FD4D69830711CAB1F8CFF25F0A329337CBA5 1904F0CAED88D61968743C8454BA922EB00038182C22FE316D16F2A9F544D6F75 D51A4E92A1C4EF8AB19A2B7FEAA32D0726C0ED80229AE6C0F7621A4209251ACE2 B2BC66FF0327A653BB686C756BE033C7A281F1D2A7E1FA31C3983E15F8FD16CC5787E6F517166814146853FF110167419A3CFDA44BE438C96F0E38BF83D9

结果是这样的: <代码>0f8006870e0c07e5091b01092f0f00ff88800223090c07e5091b01092f0 f00ff888009060100010800ff060000328902020f00161e09060100020800ff06 0000000002020f00161e09060100010700ff060000000002020f00161b0906010 0020700ff060000000002020f00161b09060100200700ff12092102020fff1623 09060100340700ff12000002020fff162309060100480700ff12000002020fff1 623090601001f0700ff12000002020ffe162109060100330700ff12000002020f fe162109060100470700ff12000002020ffe1621090601000d0700ff1203e8020 20ffd16a98558d8881285f5e85e5949158f1dbf4b91e4561312ee738fb5

(这是预期的结果)

我现在尝试使用 WebCrypto API。 但我无法让它工作。 这是我的简单代码片段:

const ba = require('binascii');
const crypto = require('crypto').webcrypto;

const myKey = "36C66639E48A8CA4D6BC8B282A793BBB";
const iv = "4B464D675000000900000023";
const cipherText = "88D5AB4F97515AAFC6B88D2F85DAA7A0E3C0C40D004535C397C9D037AB7DBDA329107615444894A1A0DD7E85F02D496CECD3FF46AF5FB3C9229CFE8F3EE4606AB2E1F409F36AAD2E50900A4396FC6C2E083F373233A69616950758BFC7D63A9E9B6E99E21B2CBC2B934772CA51FD4D69830711CAB1F8CFF25F0A329337CBA51904F0CAED88D61968743C8454BA922EB00038182C22FE316D16F2A9F544D6F75D51A4E92A1C4EF8AB19A2B7FEAA32D0726C0ED80229AE6C0F7621A4209251ACE2B2BC66FF0327A653BB686C756BE033C7A281F1D2A7E1FA31C3983E15F8FD16CC5787E6F517166814146853FF110167419A3CFDA44BE438C96F0E38BF83D9";

function importKey(rawKey) {
    console.log('e_key: ', rawKey);
    console.log('e_key: ', ba.unhexlify(rawKey));
    return crypto.subtle.importKey(
        "raw", //can be "jwk" or "raw"
        rawKey, 
        {   //this is the algorithm options
            name: "AES-GCM",
            length: 256
        },
        false, //whether the key is extractable (i.e. can be used in exportKey)
        ["encrypt", "decrypt"] //can "encrypt", "decrypt", "wrapKey", or "unwrapKey"
    )
}


function decrypt(data, key, iv) {
    console.log(data);
    return crypto.subtle.decrypt(
        {
            name: "AES-GCM",
            iv: iv, //The initialization vector you used to encrypt
            //additionalData: ArrayBuffer, //The addtionalData you used to encrypt (if any)
            //tagLength: 0, //The tagLength you used to encrypt (if any)
        },
        key, //from generateKey or importKey above
        new ArrayBuffer(data) //ArrayBuffer of the data
    ).then(function(decrypted){
        //returns an ArrayBuffer containing the decrypted data
        console.log(new Uint8Array(decrypted));
    }).catch(function(err){
        console.error(err);
    });
}

const main = async function() {
    var keys = await importKey(myKey)
    var decryptedData = await decrypt(cipherText, keys, iv);
    console.log(decryptedData);
    
};

main();

执行时,结果是:

DOMException [OperationError]: The provided data is too small.
    at asyncAesGcmCipher (node:internal/crypto/aes:202:30)
    at Object.aesCipher (node:internal/crypto/aes:229:28)
    at cipherOrWrap (node:internal/crypto/webcrypto:665:10)
    at SubtleCrypto.decrypt (node:internal/crypto/webcrypto:680:10)
    at decrypt (/Users/fritz/dev/test/simple.js:26:23)

我试图像在 python 中一样保持 1:1,但无法解密该字符串。 我尝试使用 unhexlify 等对所有实体(myKey、iv 和 cipherText)进行操作。但没有成功。

这个 JavaScript AES-GCM 与 python 库不兼容吗? 非常感谢,

干杯 弗里茨

I want to port a small python library to JavaScript, running in Node.JS.
I get an encrypted message, the initialization vector and the key.

In python3 these are the imports:

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from binascii import unhexlify
import sys
import string
from Cryptodome.Cipher import AES

And the decrypt works like this:

frame = unhexlify(frame)
encryption_key = unhexlify(str_key)
init_vector = unhexlify(str_iv)
cipher = AES.new(encryption_key, AES.MODE_GCM, nonce=init_vector)
decrypted_msg = cipher.decrypt(frame).hex()    

The key is a hexstring like this (example):
36C66639E48A8CA4D6BC8B282A793BBB

IV is this (example):
4B464D675000000900000023

Message like this:
88D5AB4F97515AAFC6B88D2F85DAA7A0E3C0C40D004535C397C9D037AB7DBDA329107615444894A1A0DD7E85F02D496CECD3FF46AF5FB3C9229CFE8F3EE4606AB2E1F409F36AAD2E50900A4396FC6C2E083F373233A69616950758BFC7D63A9E9B6E99E21B2CBC2B934772CA51FD4D69830711CAB1F8CFF25F0A329337CBA51904F0CAED88D61968743C8454BA922EB00038182C22FE316D16F2A9F544D6F75D51A4E92A1C4EF8AB19A2B7FEAA32D0726C0ED80229AE6C0F7621A4209251ACE2B2BC66FF0327A653BB686C756BE033C7A281F1D2A7E1FA31C3983E15F8FD16CC5787E6F517166814146853FF110167419A3CFDA44BE438C96F0E38BF83D9

It results in this:
0f8006870e0c07e5091b01092f0f00ff88800223090c07e5091b01092f0f00ff888009060100010800ff060000328902020f00161e09060100020800ff060000000002020f00161e09060100010700ff060000000002020f00161b09060100020700ff060000000002020f00161b09060100200700ff12092102020fff162309060100340700ff12000002020fff162309060100480700ff12000002020fff1623090601001f0700ff12000002020ffe162109060100330700ff12000002020ffe162109060100470700ff12000002020ffe1621090601000d0700ff1203e802020ffd16a98558d8881285f5e85e5949158f1dbf4b91e4561312ee738fb5

(which is the expected outcome)

I've now tried to establish the same in Javascript using the WebCrypto API.
But I can't manage it to work.
Here's my simple code snippet:

const ba = require('binascii');
const crypto = require('crypto').webcrypto;

const myKey = "36C66639E48A8CA4D6BC8B282A793BBB";
const iv = "4B464D675000000900000023";
const cipherText = "88D5AB4F97515AAFC6B88D2F85DAA7A0E3C0C40D004535C397C9D037AB7DBDA329107615444894A1A0DD7E85F02D496CECD3FF46AF5FB3C9229CFE8F3EE4606AB2E1F409F36AAD2E50900A4396FC6C2E083F373233A69616950758BFC7D63A9E9B6E99E21B2CBC2B934772CA51FD4D69830711CAB1F8CFF25F0A329337CBA51904F0CAED88D61968743C8454BA922EB00038182C22FE316D16F2A9F544D6F75D51A4E92A1C4EF8AB19A2B7FEAA32D0726C0ED80229AE6C0F7621A4209251ACE2B2BC66FF0327A653BB686C756BE033C7A281F1D2A7E1FA31C3983E15F8FD16CC5787E6F517166814146853FF110167419A3CFDA44BE438C96F0E38BF83D9";

function importKey(rawKey) {
    console.log('e_key: ', rawKey);
    console.log('e_key: ', ba.unhexlify(rawKey));
    return crypto.subtle.importKey(
        "raw", //can be "jwk" or "raw"
        rawKey, 
        {   //this is the algorithm options
            name: "AES-GCM",
            length: 256
        },
        false, //whether the key is extractable (i.e. can be used in exportKey)
        ["encrypt", "decrypt"] //can "encrypt", "decrypt", "wrapKey", or "unwrapKey"
    )
}


function decrypt(data, key, iv) {
    console.log(data);
    return crypto.subtle.decrypt(
        {
            name: "AES-GCM",
            iv: iv, //The initialization vector you used to encrypt
            //additionalData: ArrayBuffer, //The addtionalData you used to encrypt (if any)
            //tagLength: 0, //The tagLength you used to encrypt (if any)
        },
        key, //from generateKey or importKey above
        new ArrayBuffer(data) //ArrayBuffer of the data
    ).then(function(decrypted){
        //returns an ArrayBuffer containing the decrypted data
        console.log(new Uint8Array(decrypted));
    }).catch(function(err){
        console.error(err);
    });
}

const main = async function() {
    var keys = await importKey(myKey)
    var decryptedData = await decrypt(cipherText, keys, iv);
    console.log(decryptedData);
    
};

main();

When executed, it results in:

DOMException [OperationError]: The provided data is too small.
    at asyncAesGcmCipher (node:internal/crypto/aes:202:30)
    at Object.aesCipher (node:internal/crypto/aes:229:28)
    at cipherOrWrap (node:internal/crypto/webcrypto:665:10)
    at SubtleCrypto.decrypt (node:internal/crypto/webcrypto:680:10)
    at decrypt (/Users/fritz/dev/test/simple.js:26:23)

I tried to keep things 1:1 as in python, but can't decrypt this string.
I tried for all entities (myKey, iv and cipherText) with and with unhexlify, etc. No luck.

Is this JavaScript AES-GCM not compatible with the python library?
Thanks a lot,

Cheers
Fritz

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

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

发布评论

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

评论(1

懷念過去 2025-01-24 10:04:37

在这里找到答案:
https://stackoverflow.com/a/49244840/13548905
缺失的部分是身份验证标签,实际上是IV +“ 00000002”。
添加时,解密起作用。

Found the answer here:
https://stackoverflow.com/a/49244840/13548905
the missing part was the authentication tag, which in fact is IV + "00000002".
When added, decrypt worked.

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