Stack Exchange
Decrypt a AES-CTR 256 bits message from browser with window.crypto.subtle APIs
I need to decrypt in the browser a message encoded with AES-CTR 256 bits (encoded using OpenSSL).
Using OpenSSL I get something like:
key=189BBBB00C5F1FB7FBA9AD9285F193D1771D7611CB891E5C1F4E24C20E50FB1D
iv =4103C88663AE12CE18EA46E894280C4D
msg=nhVKeu8zNO2PRTwJrDE=

Well, my problem is converting those strings into objects the window.crypto.subtle APIs can manage. Eg.
const counter = ???;
const ciphertext = ???;
const rawKey = ???;

const key = window.crypto.subtle.importKey(
    "raw",
    key,
    "AES-CTR",
    true,
    ["encrypt", "decrypt"]
);

const decrypted = await window.crypto.subtle.decrypt(
{
    name: "AES-CTR",
    counter,
    length: 64
  },
  key,
  ciphertext
);

let dec = new TextDecoder();
const msg = dec.decode(decrypted);
console.log(msg);

Could anyone help me passing from key, iv, msg to counter, ciphertext, rawkey?
Thank you very much 

Key, counter (or IV) and ciphertext can be passed as TypedArray, i.e. you need two conversions, one from a hexadecimal, and a second from a Base64 encoded string into a TypedArray, e.g. 
from a hexadecimal encoded string, here:
const fromHex = hexString => new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));

from a Base64 encoded string, here:
const fromBase64 = base64String => Uint8Array.from(atob(base64String), c => c.charCodeAt(0));

In the code itself an await operator is missing and in the importKey function rawKey must be used instead of key (probably copy/paste errors). Alltogether:


const fromHex = hexString => new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
const fromBase64 = base64String => Uint8Array.from(atob(base64String), c => c.charCodeAt(0));
  
async function test(){
  
    const rawKey = fromHex("189BBBB00C5F1FB7FBA9AD9285F193D1771D7611CB891E5C1F4E24C20E50FB1D");
    const counter = fromHex("4103C88663AE12CE18EA46E894280C4D");
    const ciphertext = fromBase64("nhVKeu8zNO2PRTwJrDE=");

    const key = await window.crypto.subtle.importKey(   // add >await<
        "raw",
        rawKey,                                         // replace >key< with >rawKey<
        "AES-CTR",
        true,
        ["encrypt", "decrypt"]
    );

    const decrypted = await window.crypto.subtle.decrypt(
        {
            name: "AES-CTR",
            counter,
            length: 64
        },
        key,
        ciphertext
    );

    let dec = new TextDecoder();
    const msg = dec.decode(decrypted);
    console.log(msg);
}

test();



This decrypts the ciphertext to:
hello, world!


Thank you very much for your answer. Unfortunately, on chrome I got the error: "await is only valid in async function". However, if I remove the "await" (both), I got: "Failed to execute 'decode' on 'TextDecoder': The provided value is not of type '(ArrayBuffer or ArrayBufferView)"

await must be used in the context of an async function, see the full code in the updated solution. I have tested this solution in Chrome and it works there. So please try this. Note also, that async/await are syntactic sugar for promise use, see e.g. here and here.

Topaco, any chance you can help me with this question, too? https://stackoverflow.com/questions/61096703/decrypt-an-rsa-message-from-browser-with-window-crypto-subtle-apis?noredirect=1#comment108108734_61096703
