summaryrefslogtreecommitdiff
path: root/ext/crypto/00_crypto.js
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2021-08-26 16:18:07 +0530
committerGitHub <noreply@github.com>2021-08-26 12:48:07 +0200
commit23a9bc099d21ef7d45fe0f76e2fc53740ca98f6a (patch)
tree1fffaf83c0b6582acf33b042275e1b792a42e3e1 /ext/crypto/00_crypto.js
parent5d7d9d64434bd0a9f1fcf391dabc51693e8cf1ae (diff)
feat(ext/crypto): implement importKey and deriveBits for PBKDF2 (#11642)
Diffstat (limited to 'ext/crypto/00_crypto.js')
-rw-r--r--ext/crypto/00_crypto.js157
1 files changed, 148 insertions, 9 deletions
diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js
index fd7431b7c..5c80ac0ca 100644
--- a/ext/crypto/00_crypto.js
+++ b/ext/crypto/00_crypto.js
@@ -56,6 +56,7 @@
RsaPssParams: {},
EcdsaParams: { hash: "HashAlgorithmIdentifier" },
HmacImportParams: { hash: "HashAlgorithmIdentifier" },
+ Pbkdf2Params: { hash: "HashAlgorithmIdentifier", salt: "BufferSource" },
RsaOaepParams: { label: "BufferSource" },
};
@@ -86,6 +87,10 @@
},
"importKey": {
"HMAC": "HmacImportParams",
+ "PBKDF2": null,
+ },
+ "deriveBits": {
+ "PBKDF2": "Pbkdf2Params",
},
"encrypt": {
"RSA-OAEP": "RsaOaepParams",
@@ -657,18 +662,18 @@
const normalizedAlgorithm = normalizeAlgorithm(algorithm, "importKey");
- if (
- ArrayPrototypeFind(
- keyUsages,
- (u) => !ArrayPrototypeIncludes(["sign", "verify"], u),
- ) !== undefined
- ) {
- throw new DOMException("Invalid key usages", "SyntaxError");
- }
-
switch (normalizedAlgorithm.name) {
// https://w3c.github.io/webcrypto/#hmac-operations
case "HMAC": {
+ if (
+ ArrayPrototypeFind(
+ keyUsages,
+ (u) => !ArrayPrototypeIncludes(["sign", "verify"], u),
+ ) !== undefined
+ ) {
+ throw new DOMException("Invalid key usages", "SyntaxError");
+ }
+
switch (format) {
case "raw": {
const hash = normalizedAlgorithm.hash;
@@ -726,6 +731,52 @@
// TODO(@littledivy): RSASSA-PKCS1-v1_5
// TODO(@littledivy): RSA-PSS
// TODO(@littledivy): ECDSA
+ case "PBKDF2": {
+ // 1.
+ if (format !== "raw") {
+ throw new DOMException("Format not supported", "NotSupportedError");
+ }
+
+ // 2.
+ if (
+ ArrayPrototypeFind(
+ keyUsages,
+ (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u),
+ ) !== undefined
+ ) {
+ throw new DOMException("Invalid key usages", "SyntaxError");
+ }
+
+ // 3.
+ if (extractable !== false) {
+ throw new DOMException(
+ "Key must not be extractable",
+ "SyntaxError",
+ );
+ }
+
+ // 4.
+ const handle = {};
+ WeakMapPrototypeSet(KEY_STORE, handle, {
+ type: "raw",
+ data: keyData,
+ });
+
+ // 5-9.
+ const algorithm = {
+ name: "PBKDF2",
+ };
+ const key = constructKey(
+ "secret",
+ false,
+ usageIntersection(keyUsages, recognisedUsages),
+ algorithm,
+ handle,
+ );
+
+ // 10.
+ return key;
+ }
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
@@ -783,6 +834,48 @@
}
/**
+ * @param {AlgorithmIdentifier} algorithm
+ * @param {CryptoKey} baseKey
+ * @param {number} length
+ * @returns {Promise<ArrayBuffer>}
+ */
+ async deriveBits(algorithm, baseKey, length) {
+ webidl.assertBranded(this, SubtleCrypto);
+ const prefix = "Failed to execute 'deriveBits' on 'SubtleCrypto'";
+ webidl.requiredArguments(arguments.length, 3, { prefix });
+ algorithm = webidl.converters.AlgorithmIdentifier(algorithm, {
+ prefix,
+ context: "Argument 1",
+ });
+ baseKey = webidl.converters.CryptoKey(baseKey, {
+ prefix,
+ context: "Argument 2",
+ });
+ length = webidl.converters["unsigned long"](length, {
+ prefix,
+ context: "Argument 3",
+ });
+
+ // 2.
+ const normalizedAlgorithm = normalizeAlgorithm(algorithm, "deriveBits");
+ // 4-6.
+ const result = await deriveBits(normalizedAlgorithm, baseKey, length);
+ // 7.
+ if (normalizedAlgorithm.name !== baseKey[_algorithm].name) {
+ throw new DOMException("InvalidAccessError", "Invalid algorithm name");
+ }
+ // 8.
+ if (!ArrayPrototypeIncludes(baseKey[_usages], "deriveBits")) {
+ throw new DOMException(
+ "InvalidAccessError",
+ "baseKey usages does not contain `deriveBits`",
+ );
+ }
+ // 9-10.
+ return result;
+ }
+
+ /**
* @param {string} algorithm
* @param {CryptoKey} key
* @param {BufferSource} signature
@@ -1185,6 +1278,52 @@
}
}
+ async function deriveBits(normalizedAlgorithm, baseKey, length) {
+ switch (normalizedAlgorithm.name) {
+ case "PBKDF2": {
+ // 1.
+ if (length == null || length == 0 || length % 8 !== 0) {
+ throw new DOMException("Invalid length", "OperationError");
+ }
+
+ if (normalizedAlgorithm.iterations == 0) {
+ throw new DOMException(
+ "iterations must not be zero",
+ "OperationError",
+ );
+ }
+
+ const handle = baseKey[_handle];
+ const keyData = WeakMapPrototypeGet(KEY_STORE, handle);
+
+ if (ArrayBufferIsView(normalizedAlgorithm.salt)) {
+ normalizedAlgorithm.salt = new Uint8Array(
+ normalizedAlgorithm.salt.buffer,
+ normalizedAlgorithm.salt.byteOffset,
+ normalizedAlgorithm.salt.byteLength,
+ );
+ } else {
+ normalizedAlgorithm.salt = new Uint8Array(normalizedAlgorithm.salt);
+ }
+ normalizedAlgorithm.salt = TypedArrayPrototypeSlice(
+ normalizedAlgorithm.salt,
+ );
+
+ const buf = await core.opAsync("op_crypto_derive_bits", {
+ key: keyData,
+ algorithm: "PBKDF2",
+ hash: normalizedAlgorithm.hash.name,
+ iterations: normalizedAlgorithm.iterations,
+ length,
+ }, normalizedAlgorithm.salt);
+
+ return buf.buffer;
+ }
+ default:
+ throw new DOMException("Not implemented", "NotSupportedError");
+ }
+ }
+
const subtle = webidl.createBranded(SubtleCrypto);
class Crypto {