I want to perform basic AES-CBC decryption. I have the string encData
that is encrypted with the 128-bits key rawKey
, the initialization vector defaultIV
is zero. I want to use only Web Crypto API, without 3th-party libraries. Is it possible to do?
window.crypto.subtle.decrypt
of Web Crypto API throws the exception when I use it: DOMException
(and no more information) in Chromium and OperationError: The operation failed for an operation-specific reason
in Firefox.
What is it the problem?
The key and encrypted data is OK, I have checked it in an online decryption (use the hex string from the console output).
The code:
!async function script() {
// ArrayBuffer to Hex String.
function buf2hex(buffer) {
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}
const defaultIV = new Uint8Array(16);
const rawKey = new Uint8Array([42, 40, 254, 9, 99, 201, 174, 52, 226, 21, 90, 155, 81, 50, 2, 9]);
const encData = new Uint8Array([102, 80, 220, 73, 185, 233, 85, 7, 195, 196, 137, 107, 65, 150, 162, 161, 80, 82, 26, 18, 110, 247, 189, 176, 35, 197, 140, 4, 138, 75, 159, 197, 75, 88, 131, 23, 235, 125, 96, 81, 41, 170, 220, 45, 64, 55, 30, 68, 39, 6, 112, 194, 243, 209, 177, 173, 54, 71, 21, 172, 62, 147, 112, 76]);
console.log("defaultIV\n", defaultIV, buf2hex(defaultIV));
console.log("rawKey\n", rawKey, buf2hex(rawKey));
console.log("encData\n", encData, buf2hex(encData));
const key = await crypto.subtle.importKey(
"raw",
rawKey,
"AES-CBC",
true,
["decrypt"]
);
console.log("key", key);
// It throws "Uncaught (in promise) DOMException"
const decrypted = await crypto.subtle.decrypt(
{
name: "AES-CBC",
iv: defaultIV
},
key,
encData
);
console.log("decrypted", decrypted);
}();
I want to perform basic AES-CBC decryption. I have the string encData
that is encrypted with the 128-bits key rawKey
, the initialization vector defaultIV
is zero. I want to use only Web Crypto API, without 3th-party libraries. Is it possible to do?
window.crypto.subtle.decrypt
of Web Crypto API throws the exception when I use it: DOMException
(and no more information) in Chromium and OperationError: The operation failed for an operation-specific reason
in Firefox.
What is it the problem?
The key and encrypted data is OK, I have checked it in an online decryption (use the hex string from the console output).
The code:
!async function script() {
// ArrayBuffer to Hex String. https://stackoverflow./a/40031979/11468937
function buf2hex(buffer) {
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}
const defaultIV = new Uint8Array(16);
const rawKey = new Uint8Array([42, 40, 254, 9, 99, 201, 174, 52, 226, 21, 90, 155, 81, 50, 2, 9]);
const encData = new Uint8Array([102, 80, 220, 73, 185, 233, 85, 7, 195, 196, 137, 107, 65, 150, 162, 161, 80, 82, 26, 18, 110, 247, 189, 176, 35, 197, 140, 4, 138, 75, 159, 197, 75, 88, 131, 23, 235, 125, 96, 81, 41, 170, 220, 45, 64, 55, 30, 68, 39, 6, 112, 194, 243, 209, 177, 173, 54, 71, 21, 172, 62, 147, 112, 76]);
console.log("defaultIV\n", defaultIV, buf2hex(defaultIV));
console.log("rawKey\n", rawKey, buf2hex(rawKey));
console.log("encData\n", encData, buf2hex(encData));
const key = await crypto.subtle.importKey(
"raw",
rawKey,
"AES-CBC",
true,
["decrypt"]
);
console.log("key", key);
// It throws "Uncaught (in promise) DOMException"
const decrypted = await crypto.subtle.decrypt(
{
name: "AES-CBC",
iv: defaultIV
},
key,
encData
);
console.log("decrypted", decrypted);
}();
Share
Improve this question
edited Feb 8, 2020 at 2:16
KeyKi
asked Feb 7, 2020 at 23:57
KeyKiKeyKi
3,2433 gold badges15 silver badges30 bronze badges
6
-
The expected output is:
MEGA{"n":"SharedFile.jpg","c":"GRSM8+c1HUmlmyDuTJVrDwSDpqRV"}
I have used aes.online-domain-tools. – KeyKi Commented Feb 8, 2020 at 0:14 - DOM Exception is the document object model. It's your browser plaining about your client side code. I'll look into that library. – Sydney Y Commented Feb 8, 2020 at 0:51
-
In Firefox I get
OperationError: The operation failed for an operation-specific reason
. – KeyKi Commented Feb 8, 2020 at 0:56 - I'm at a loss right now. Can you tell me what it is you are trying to do? I'm pretty confident in JavaScript so I think I can help, but I'm not familiar with cryptography. Example: "I have a JSON string encrypted and hashed that I am trying to decode" – Sydney Y Commented Feb 8, 2020 at 1:57
-
A basic AES-CBC decryption. I have a string
encData
that is encrypted with a 128-bits keyrawKey
, an initialization vectordefaultIV
is zero. I wanted to useWeb Crypto API
, without 3th-party libraries. – KeyKi Commented Feb 8, 2020 at 2:11
2 Answers
Reset to default 7A padding (PKCS #7). It was the problem. My encrypted text that I get from a 3th-party service has no padding (that adds before encryption).
Web Crypto API does not work with data encrypted without the padding.
AES-JS has easy to use API, but it works only with a text without the padding (In my case it's OK), but if you use it to decrypt a cipher text with the padding you need to manually remove it from the result string.
CryptoJS API looks ancient, but it works fine in both case, when the text has the padding or not.
You need to transform ArrayBuffer to something other:
let key = ab_to_hex(keyArrayBuffer);
let iv = ab_to_bin_str(ivArrayBuffer);
let encrypted = ab_to_bin_str(encryptedArrayBuffer);
function decrypt(key, iv, encrypted) {
const plaintextArray = CryptoJS.AES.decrypt(
{ ciphertext: CryptoJS.enc.Latin1.parse(encrypted) },
CryptoJS.enc.Hex.parse(key),
{ iv: CryptoJS.enc.Latin1.parse(iv) }
);
return CryptoJS.enc.Utf8.stringify(plaintextArray);
}
function ab_to_hex(buffer) {
return Array.from(new Uint8Array(buffer)).map(n => ("0" + n.toString(16)).slice(-2)).join("");
}
function ab_to_bin_str(buffer) {
return String.fromCharCode(...new Uint8Array(buffer));
}
See this post, better to use AES-GCM if possible: Webcrypto AES-CBC Decrypt: Operation Error - The operation failed for an operation-specific reason
You can test your browser version for what it supports using this test suite - https://peculiarventures.github.io/pv-webcrypto-tests/
It is certainly possible to do AES-CBC with WebCrypto: https://github./diafygi/webcrypto-examples#aes-cbc