I've got the following code to generate a key using the Web Crypto API in the browser:
const IV = new Uint8Array([
181, 205, 79, 202, 71, 30,
192, 175, 44, 93, 57, 15,
106, 207, 83, 179
]);
const SALT = "I'm so salty!";
async function generateKey(password, crypto) {
const enc = new TextEncoder();
const keyMaterial = await crypto.subtle.importKey(
"raw",
enc.encode(password),
"PBKDF2",
false,
["deriveBits", "deriveKey"],
);
return await crypto.subtle.deriveKey(
{
name: "PBKDF2",
salt: SALT,
iterations: 100000,
hash: "SHA-256",
},
keyMaterial,
{ "name": "AES-GCM", "length": 256},
true,
["encrypt", "decrypt"],
);
}
When called like this:
await generateKey("some password", window.crypto)
the deriveKey
function throws an exception Uncaught (in promise) DOMException: An invalid or illegal string was specified
with no further details provided. What am I doing wrong? Btw, I'm on latest Firefox Developer edition.
Note that when called in NodeJS as
import { webcrypto } from "crypto";
await generateKey("some password", webcrypto)
it works just fine.
CodePudding user response:
On the docs for the PBKDF2 algorithm config, the SALT must be an ArrayBuffer, a TypedArray, or a DataView. You are passing a string. I believe you can use the existing text encoder you already have (though I have not tested this):
salt: enc.encode(SALT),
Note: the code from your question throws a different-yet-more-helpful error in Chrome.