mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 16:42:21 -05:00
feat(ext/crypto): implement wrapKey (#12125)
This commit is contained in:
parent
b354eaa247
commit
5065c7bcd9
4 changed files with 145 additions and 3 deletions
|
@ -499,3 +499,40 @@ unitTest(async function testHkdfDeriveBits() {
|
||||||
);
|
);
|
||||||
assertEquals(result.byteLength, 128 / 8);
|
assertEquals(result.byteLength, 128 / 8);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
unitTest(async function testWrapKey() {
|
||||||
|
// Test wrapKey
|
||||||
|
const key = await crypto.subtle.generateKey(
|
||||||
|
{
|
||||||
|
name: "RSA-OAEP",
|
||||||
|
modulusLength: 4096,
|
||||||
|
publicExponent: new Uint8Array([1, 0, 1]),
|
||||||
|
hash: "SHA-256",
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
["wrapKey", "unwrapKey"],
|
||||||
|
);
|
||||||
|
|
||||||
|
const hmacKey = await crypto.subtle.generateKey(
|
||||||
|
{
|
||||||
|
name: "HMAC",
|
||||||
|
hash: "SHA-256",
|
||||||
|
length: 128,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
["sign"],
|
||||||
|
);
|
||||||
|
|
||||||
|
const wrappedKey = await crypto.subtle.wrapKey(
|
||||||
|
"raw",
|
||||||
|
hmacKey,
|
||||||
|
key.publicKey,
|
||||||
|
{
|
||||||
|
name: "RSA-OAEP",
|
||||||
|
label: new Uint8Array(8),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(wrappedKey instanceof ArrayBuffer);
|
||||||
|
assertEquals(wrappedKey.byteLength, 512);
|
||||||
|
});
|
||||||
|
|
|
@ -120,6 +120,10 @@
|
||||||
"decrypt": {
|
"decrypt": {
|
||||||
"RSA-OAEP": "RsaOaepParams",
|
"RSA-OAEP": "RsaOaepParams",
|
||||||
},
|
},
|
||||||
|
"wrapKey": {
|
||||||
|
// TODO(@littledivy): Enable this once implemented.
|
||||||
|
// "AES-KW": "AesKeyWrapParams",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Decodes the unpadded base64 to the octet sequence containing key value `k` defined in RFC7518 Section 6.4
|
// Decodes the unpadded base64 to the octet sequence containing key value `k` defined in RFC7518 Section 6.4
|
||||||
|
@ -1519,6 +1523,104 @@
|
||||||
throw new TypeError("unreachable");
|
throw new TypeError("unreachable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} algorithm
|
||||||
|
* @param {boolean} extractable
|
||||||
|
* @param {KeyUsage[]} keyUsages
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
*/
|
||||||
|
async wrapKey(format, key, wrappingKey, wrapAlgorithm) {
|
||||||
|
webidl.assertBranded(this, SubtleCrypto);
|
||||||
|
const prefix = "Failed to execute 'wrapKey' on 'SubtleCrypto'";
|
||||||
|
webidl.requiredArguments(arguments.length, 4, { prefix });
|
||||||
|
format = webidl.converters.KeyFormat(format, {
|
||||||
|
prefix,
|
||||||
|
context: "Argument 1",
|
||||||
|
});
|
||||||
|
key = webidl.converters.CryptoKey(key, {
|
||||||
|
prefix,
|
||||||
|
context: "Argument 2",
|
||||||
|
});
|
||||||
|
wrappingKey = webidl.converters.CryptoKey(wrappingKey, {
|
||||||
|
prefix,
|
||||||
|
context: "Argument 3",
|
||||||
|
});
|
||||||
|
wrapAlgorithm = webidl.converters.AlgorithmIdentifier(wrapAlgorithm, {
|
||||||
|
prefix,
|
||||||
|
context: "Argument 4",
|
||||||
|
});
|
||||||
|
|
||||||
|
let normalizedAlgorithm;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 2.
|
||||||
|
normalizedAlgorithm = normalizeAlgorithm(wrapAlgorithm, "wrapKey");
|
||||||
|
} catch (_) {
|
||||||
|
// 3.
|
||||||
|
normalizedAlgorithm = normalizeAlgorithm(wrapAlgorithm, "encrypt");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8.
|
||||||
|
if (normalizedAlgorithm.name !== wrappingKey[_algorithm].name) {
|
||||||
|
throw new DOMException(
|
||||||
|
"Wrapping algorithm doesn't match key algorithm.",
|
||||||
|
"InvalidAccessError",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9.
|
||||||
|
if (!ArrayPrototypeIncludes(wrappingKey[_usages], "wrapKey")) {
|
||||||
|
throw new DOMException(
|
||||||
|
"Key does not support the 'wrapKey' operation.",
|
||||||
|
"InvalidAccessError",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 10. NotSupportedError will be thrown in step 12.
|
||||||
|
// 11.
|
||||||
|
if (key[_extractable] === false) {
|
||||||
|
throw new DOMException(
|
||||||
|
"Key is not extractable",
|
||||||
|
"InvalidAccessError",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 12.
|
||||||
|
const exportedKey = await this.exportKey(format, key);
|
||||||
|
|
||||||
|
let bytes;
|
||||||
|
// 13.
|
||||||
|
if (format !== "jwk") {
|
||||||
|
bytes = exportedKey;
|
||||||
|
} else {
|
||||||
|
// TODO(@littledivy): Implement JWK.
|
||||||
|
throw new DOMException(
|
||||||
|
"Not implemented",
|
||||||
|
"NotSupportedError",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 14-15.
|
||||||
|
if (
|
||||||
|
supportedAlgorithms["wrapKey"][normalizedAlgorithm.name] !== undefined
|
||||||
|
) {
|
||||||
|
// TODO(@littledivy): Implement this for AES-KW.
|
||||||
|
throw new DOMException(
|
||||||
|
"Not implemented",
|
||||||
|
"NotSupportedError",
|
||||||
|
);
|
||||||
|
} else if (
|
||||||
|
supportedAlgorithms["encrypt"][normalizedAlgorithm.name] !== undefined
|
||||||
|
) {
|
||||||
|
return this.encrypt(normalizedAlgorithm, wrappingKey, bytes);
|
||||||
|
} else {
|
||||||
|
throw new DOMException(
|
||||||
|
"Algorithm not supported",
|
||||||
|
"NotSupportedError",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} algorithm
|
* @param {string} algorithm
|
||||||
* @param {boolean} extractable
|
* @param {boolean} extractable
|
||||||
|
|
6
ext/crypto/lib.deno_crypto.d.ts
vendored
6
ext/crypto/lib.deno_crypto.d.ts
vendored
|
@ -215,6 +215,12 @@ interface SubtleCrypto {
|
||||||
baseKey: CryptoKey,
|
baseKey: CryptoKey,
|
||||||
length: number,
|
length: number,
|
||||||
): Promise<ArrayBuffer>;
|
): Promise<ArrayBuffer>;
|
||||||
|
wrapKey(
|
||||||
|
format: KeyFormat,
|
||||||
|
key: CryptoKey,
|
||||||
|
wrappingKey: CryptoKey,
|
||||||
|
wrapAlgorithm: AlgorithmIdentifier | RsaOaepParams,
|
||||||
|
): Promise<ArrayBuffer>;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare interface Crypto {
|
declare interface Crypto {
|
||||||
|
|
|
@ -12149,12 +12149,9 @@
|
||||||
"historical.any.html": false,
|
"historical.any.html": false,
|
||||||
"idlharness.https.any.html": [
|
"idlharness.https.any.html": [
|
||||||
"SubtleCrypto interface: operation deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>)",
|
"SubtleCrypto interface: operation deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>)",
|
||||||
"SubtleCrypto interface: operation wrapKey(KeyFormat, CryptoKey, CryptoKey, AlgorithmIdentifier)",
|
|
||||||
"SubtleCrypto interface: operation unwrapKey(KeyFormat, BufferSource, CryptoKey, AlgorithmIdentifier, AlgorithmIdentifier, boolean, sequence<KeyUsage>)",
|
"SubtleCrypto interface: operation unwrapKey(KeyFormat, BufferSource, CryptoKey, AlgorithmIdentifier, AlgorithmIdentifier, boolean, sequence<KeyUsage>)",
|
||||||
"SubtleCrypto interface: crypto.subtle must inherit property \"deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>)\" with the proper type",
|
"SubtleCrypto interface: crypto.subtle must inherit property \"deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>)\" with the proper type",
|
||||||
"SubtleCrypto interface: calling deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>) on crypto.subtle with too few arguments must throw TypeError",
|
"SubtleCrypto interface: calling deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>) on crypto.subtle with too few arguments must throw TypeError",
|
||||||
"SubtleCrypto interface: crypto.subtle must inherit property \"wrapKey(KeyFormat, CryptoKey, CryptoKey, AlgorithmIdentifier)\" with the proper type",
|
|
||||||
"SubtleCrypto interface: calling wrapKey(KeyFormat, CryptoKey, CryptoKey, AlgorithmIdentifier) on crypto.subtle with too few arguments must throw TypeError",
|
|
||||||
"SubtleCrypto interface: crypto.subtle must inherit property \"unwrapKey(KeyFormat, BufferSource, CryptoKey, AlgorithmIdentifier, AlgorithmIdentifier, boolean, sequence<KeyUsage>)\" with the proper type",
|
"SubtleCrypto interface: crypto.subtle must inherit property \"unwrapKey(KeyFormat, BufferSource, CryptoKey, AlgorithmIdentifier, AlgorithmIdentifier, boolean, sequence<KeyUsage>)\" with the proper type",
|
||||||
"SubtleCrypto interface: calling unwrapKey(KeyFormat, BufferSource, CryptoKey, AlgorithmIdentifier, AlgorithmIdentifier, boolean, sequence<KeyUsage>) on crypto.subtle with too few arguments must throw TypeError",
|
"SubtleCrypto interface: calling unwrapKey(KeyFormat, BufferSource, CryptoKey, AlgorithmIdentifier, AlgorithmIdentifier, boolean, sequence<KeyUsage>) on crypto.subtle with too few arguments must throw TypeError",
|
||||||
"Window interface: attribute crypto"
|
"Window interface: attribute crypto"
|
||||||
|
|
Loading…
Reference in a new issue