首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在SJCL库解密AES SubtleCrypto网络API

如何在SJCL库解密AES SubtleCrypto网络API
EN

Stack Overflow用户
提问于 2021-12-12 07:27:03
回答 1查看 599关注 0票数 1

我们有一个世博反应本地项目使用加密。我们当前的加密基于SubtleCrypto / Web window.subtle.crypto,使用的是AES-GCM 128,现在我们需要使用一个在所有平台上普遍可用的库-- Web、iOS和Android。从我前面的问题中,我们找到了支持GCM模式的SJCL,我们可以完全替换所有基于web的代码,但挑战是我们需要确保所有当前加密的数据也在这个新的库中解密,我们必须这样做:

window.crypto.subtle.encrypt AES-GCM 128 => (a) -> SJCL.mode.gcm.decrypt(a)

一旦我们成功地做到了这一点,我们就可以完全取代这个库,并具有通用的平台支持和向后兼容性。

这意味着我们根本无法改变加密的处理方式,因为这是必需的,而且我们正在加密它,就像下面的代码一样。

我通过一条很好的线索获得了Neneil94,但在编码/格式方面仍然面临问题;下面是当前的代码:

代码语言:javascript
复制
function arrayBufferToString(buffer){
    var str = "";
    for (var iii = 0; iii < buffer.byteLength; iii++){
        str += String.fromCharCode(buffer[iii]);
    }
    return str;
}

const generateKey = async () =>
{
    const key = await window.crypto.subtle.generateKey(
    {
        name: "AES-GCM",
        length: 128
    }, true, ["encrypt", "decrypt"]);
    const key_exported = await window.crypto.subtle.exportKey("jwk", key);
    return key_exported.k;
}

const text = "This is an encrypted message";
const printCurrent = async () =>
{
    let kkey = await generateKey();
    await window.crypto.subtle.importKey(
        "jwk",
        {
            k: kkey,
            alg: "A128GCM",
            ext: true,
            key_ops: ["encrypt", "decrypt"],
            kty: "oct",
        },
        {
            name: "AES-GCM",
            length: 128
        },
        false,
        ["encrypt", "decrypt"]
    ).then(function(key)
    {
        window.crypto.subtle.encrypt(
        {
            name: "AES-GCM",
            iv: new Uint8Array(12)
        }, key, new TextEncoder().encode(JSON.stringify(text))).then(function(encryptedObject)
        {
            console.log({kkey}); //{kkey: 'eKM_Cen2Z-jhedM284cltA'}

            let bkey = sjcl.codec.utf8String.toBits(kkey);
            console.log({bkey}); //{bkey: Array(6)}
            let cipher = new sjcl.cipher.aes(bkey);
            //let bdata = sjcl.codec.base64.toBits(encryptedObject); //gives error of a.replace
            let bdata = arrayBufferToString(encryptedObject);
            let ivvv = new Uint8Array(12);
            let ivv = Buffer.from(ivvv).toString('base64');
            let ive = sjcl.codec.base64.toBits(ivv);

            // decrypt
            let decbits = sjcl.mode.gcm.decrypt(cipher, bdata, ive);

            // convert into utf8string
            decryptedData = sjcl.codec.utf8String.fromBits(decbits);
        });
    });
}

我得到的错误是:

损坏: gcm:标记不匹配

我不知道aesKey在Neneil上面链接的代码到底是什么,是CryptoKey对象还是从JsonWebKey生成的22个字符?对于“encryptedObject”,我将如何将其转换为BitArray。对于静脉输液,我只是提供了加密所做的事情,但我也不确定..

尽管如此,任何洞察力都会很有帮助,谢谢你的时间!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-12 11:25:00

代码中有两个问题:

  • kkey是Base64url编码的原始密钥。这必须首先转换为Base64,然后转换为bitArray。
代码语言:javascript
复制
let kkeyB64 = kkey.replace(/-/g, '+').replace(/_/g, '/');   // Base64url -> Base64 (ignore optional padding)
let bkey = sjcl.codec.base64.toBits(kkeyB64);               // conert to bitArray
代码语言:javascript
复制
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/sjcl@1.0.8/core/codecArrayBuffer.js"></script>
代码语言:javascript
复制
let bdata = sjcl.codec.arrayBuffer.toBits(encryptedObject)
let ive = sjcl.codec.arrayBuffer.toBits(new Uint8Array(12).buffer)

通过这些更改,使用sjcl解密是成功的。

完整代码:

代码语言:javascript
复制
const generateKey = async () =>
{
    const key = await window.crypto.subtle.generateKey(
    {
        name: "AES-GCM",
        length: 128
    }, true, ["encrypt", "decrypt"]);
    const key_exported = await window.crypto.subtle.exportKey("jwk", key);
    return key_exported.k;
}

const text = "This is an encrypted message";
const printCurrent = async () =>
{
    let kkey = await generateKey();
    await window.crypto.subtle.importKey(
        "jwk",
        {
            k: kkey,
            alg: "A128GCM",
            ext: true,
            key_ops: ["encrypt", "decrypt"],
            kty: "oct",
        },
        {
            name: "AES-GCM",
            length: 128
        },
        false,
        ["encrypt", "decrypt"]
    ).then(function(key)
    {
        window.crypto.subtle.encrypt(
        {
            name: "AES-GCM",
            iv: new Uint8Array(12)
        }, key, new TextEncoder().encode(JSON.stringify(text))).then(function(encryptedObject)
        {
            //console.log({kkey}); //{kkey: 'eKM_Cen2Z-jhedM284cltA'}

            let kkeyB64 = kkey.replace(/-/g, '+').replace(/_/g, '/'); // Fix 1
            let bkey = sjcl.codec.base64.toBits(kkeyB64); 
            //console.log({bkey}); //{bkey: Array(6)}
            let cipher = new sjcl.cipher.aes(bkey);
            
            
            let bdata = sjcl.codec.arrayBuffer.toBits(encryptedObject) // Fix 2
            let ive = sjcl.codec.arrayBuffer.toBits(new Uint8Array(12).buffer) // Fix 3
            
            // decrypt
            let decbits = sjcl.mode.gcm.decrypt(cipher, bdata, ive);

            // convert into utf8string
            decryptedData = sjcl.codec.utf8String.fromBits(decbits);
            document.getElementById("pt").innerHTML = JSON.parse(decryptedData);
        });
    });
}

printCurrent();
代码语言:javascript
复制
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/sjcl@1.0.8/sjcl.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/sjcl@1.0.8/core/codecArrayBuffer.js"></script>
<p style="font-family:'Courier New', monospace;" id="pt"></p>

如果由于某些原因(我不确定),ArrayBuffer编解码器在您的环境中不可用,那么ArrayBuffer也可以显式十六进制或Base64编码,然后转换为bitArray,例如:

代码语言:javascript
复制
// https://stackoverflow.com/a/40031979/9014097
function buf2hex(buffer) { 
    return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}
...
let bdata = sjcl.codec.hex.toBits(buf2hex(encryptedObject)) 
let ive = sjcl.codec.hex.toBits(buf2hex(new Uint8Array(12).buffer)) 

安保:

静态IV (与new Uint8Array(12)一样)是GCM上下文中的致命错误,例如这里。相反,将为每个加密生成一个随机IV,这些加密将与密文一起传递(通常是级联的)。因此,除非静态IV只用于测试目的,否则这必须是固定的。

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

https://stackoverflow.com/questions/70321733

复制
相关文章

相似问题

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