0

Here's my code:

var key = 'aaaaaaaaaaaaaaaa'
var iv = 'bbbbbbbbbbbbbbbb';
var ciphertext = '10f42fd95857ed2775cfbc4b471bc213';

// from https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey#PKCS_8_import
function str2ab(str) {
    const buf = new ArrayBuffer(str.length);
    const bufView = new Uint8Array(buf);
    for (let i = 0, strLen = str.length; i < strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}

key = new TextEncoder().encode(key);
iv = new TextEncoder().encode(iv);
ciphertext = str2ab(ciphertext);

window.crypto.subtle.importKey(
    'raw',
    key,
    {
        name: 'AES-CBC'
    },
    true, // can the key be extracted using SubtleCrypto.exportKey() / SubtleCrypto.wrapKey()?
    ['decrypt'] // keyUsages
).then(function(key) {
    window.crypto.subtle.decrypt(
        {
            name: "AES-CBC",
            iv: iv
        },
        key,
        ciphertext
    ).then(function(plaintext) {
        console.log(new TextDecoder().decode(plaintext));
    })
});

When I run it I get Uncaught (in promise) Error in the JS Console.

Here's a JSFiddle showing the error:

https://jsfiddle.net/96gx7hz3/

Any ideas?

3
  • can't see the error on linked fiddle - EDIT: actually, can see the error on browser's console, not on jsfiddle console Commented Mar 5, 2024 at 12:16
  • 1
    The hex decoding of the ciphertext is missing. Commented Mar 5, 2024 at 12:23
  • 1
    I'm pretty sure that using a key as string will not work correctly, it needs to be a byte array or similar, read the documentation. Bytes and IV should be bytes when provided (and yes, the API is shit). Commented Mar 5, 2024 at 16:50

1 Answer 1

2

The ciphertext is hex encoded and must therefore be hex decoded, e.g. with the following helper function:

function hex2ab(hex){
    return new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {return parseInt(h, 16)}));
}

The str2ab() function used in the code is commonly applied for a latin1 encoding, which however would be wrong in this case.

With this change, decryption works:

var key = 'aaaaaaaaaaaaaaaa'
var iv = 'bbbbbbbbbbbbbbbb';
var ciphertext = '10f42fd95857ed2775cfbc4b471bc213';

/*
// from https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey#PKCS_8_import
function str2ab(str) {
    const buf = new ArrayBuffer(str.length);
    const bufView = new Uint8Array(buf);
    for (let i = 0, strLen = str.length; i < strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}
*/
function hex2ab(hex){
    return new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {return parseInt(h, 16)}));
}

key = new TextEncoder().encode(key);
iv = new TextEncoder().encode(iv);
//ciphertext = str2ab(ciphertext);
ciphertext = hex2ab(ciphertext); // Fix: Replcae latin1 encoding with hex decoding

window.crypto.subtle.importKey(
    'raw',
    key,
    {
        name: 'AES-CBC'
    },
    true, // can the key be extracted using SubtleCrypto.exportKey() / SubtleCrypto.wrapKey()?
    ['decrypt'] // keyUsages
).then(function(key) {
    window.crypto.subtle.decrypt(
        {
            name: "AES-CBC",
            iv: iv
        },
        key,
        ciphertext
    ).then(function(plaintext) {
        console.log(new TextDecoder().decode(plaintext));
    })
});


A note on key and IV: In the code, the key material is UTF-8 encoded and used directly as key. This is fine for testing purposes as here, but in general a key should be generated as a random byte sequence or, if a passphrase is used, derived using a key derivation function in conjunction with a random salt.
Likewise, to avoid reusing key/IV pairs, no static IV may be applied. Instead, a random IV is commonly generated for each encryption and passed along with the ciphertext.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.