mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 00:29:09 -05:00
feat(ext/crypto): AES key generation (#11869)
Support AES-CTR, AES-CBC, AES-GCM, and AES-KW in SubtleCrypto#generateKey.
This commit is contained in:
parent
fcd0992dba
commit
cee5be4539
4 changed files with 107 additions and 1414 deletions
|
@ -77,6 +77,10 @@
|
||||||
"RSA-PSS": "RsaHashedKeyGenParams",
|
"RSA-PSS": "RsaHashedKeyGenParams",
|
||||||
"RSA-OAEP": "RsaHashedKeyGenParams",
|
"RSA-OAEP": "RsaHashedKeyGenParams",
|
||||||
"ECDSA": "EcKeyGenParams",
|
"ECDSA": "EcKeyGenParams",
|
||||||
|
"AES-CTR": "AesKeyGenParams",
|
||||||
|
"AES-CBC": "AesKeyGenParams",
|
||||||
|
"AES-GCM": "AesKeyGenParams",
|
||||||
|
"AES-KW": "AesKeyGenParams",
|
||||||
"HMAC": "HmacKeyGenParams",
|
"HMAC": "HmacKeyGenParams",
|
||||||
},
|
},
|
||||||
"sign": {
|
"sign": {
|
||||||
|
@ -1415,10 +1419,40 @@
|
||||||
return { publicKey, privateKey };
|
return { publicKey, privateKey };
|
||||||
}
|
}
|
||||||
// TODO(lucacasonato): ECDH
|
// TODO(lucacasonato): ECDH
|
||||||
// TODO(lucacasonato): AES-CTR
|
case "AES-CTR":
|
||||||
// TODO(lucacasonato): AES-CBC
|
case "AES-CBC":
|
||||||
// TODO(lucacasonato): AES-GCM
|
case "AES-GCM": {
|
||||||
// TODO(lucacasonato): AES-KW
|
// 1.
|
||||||
|
if (
|
||||||
|
ArrayPrototypeFind(
|
||||||
|
usages,
|
||||||
|
(u) =>
|
||||||
|
!ArrayPrototypeIncludes([
|
||||||
|
"encrypt",
|
||||||
|
"decrypt",
|
||||||
|
"wrapKey",
|
||||||
|
"unwrapKey",
|
||||||
|
], u),
|
||||||
|
) !== undefined
|
||||||
|
) {
|
||||||
|
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||||
|
}
|
||||||
|
|
||||||
|
return generateKeyAES(normalizedAlgorithm, extractable, usages);
|
||||||
|
}
|
||||||
|
case "AES-KW": {
|
||||||
|
// 1.
|
||||||
|
if (
|
||||||
|
ArrayPrototypeFind(
|
||||||
|
usages,
|
||||||
|
(u) => !ArrayPrototypeIncludes(["wrapKey", "unwrapKey"], u),
|
||||||
|
) !== undefined
|
||||||
|
) {
|
||||||
|
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||||
|
}
|
||||||
|
|
||||||
|
return generateKeyAES(normalizedAlgorithm, extractable, usages);
|
||||||
|
}
|
||||||
case "HMAC": {
|
case "HMAC": {
|
||||||
// 1.
|
// 1.
|
||||||
if (
|
if (
|
||||||
|
@ -1473,6 +1507,42 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function generateKeyAES(normalizedAlgorithm, extractable, usages) {
|
||||||
|
// 2.
|
||||||
|
if (!ArrayPrototypeIncludes([128, 192, 256], normalizedAlgorithm.length)) {
|
||||||
|
throw new DOMException("Invalid key length", "OperationError");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.
|
||||||
|
const keyData = await core.opAsync("op_crypto_generate_key", {
|
||||||
|
name: normalizedAlgorithm.name,
|
||||||
|
length: normalizedAlgorithm.length,
|
||||||
|
});
|
||||||
|
const handle = {};
|
||||||
|
WeakMapPrototypeSet(KEY_STORE, handle, {
|
||||||
|
type: "raw",
|
||||||
|
data: keyData,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 6-8.
|
||||||
|
const algorithm = {
|
||||||
|
name: normalizedAlgorithm.name,
|
||||||
|
length: normalizedAlgorithm.length,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 9-11.
|
||||||
|
const key = constructKey(
|
||||||
|
"secret",
|
||||||
|
extractable,
|
||||||
|
usages,
|
||||||
|
algorithm,
|
||||||
|
handle,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 12.
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
async function deriveBits(normalizedAlgorithm, baseKey, length) {
|
async function deriveBits(normalizedAlgorithm, baseKey, length) {
|
||||||
switch (normalizedAlgorithm.name) {
|
switch (normalizedAlgorithm.name) {
|
||||||
case "PBKDF2": {
|
case "PBKDF2": {
|
||||||
|
|
|
@ -117,6 +117,19 @@
|
||||||
webidl.converters.EcKeyGenParams = webidl
|
webidl.converters.EcKeyGenParams = webidl
|
||||||
.createDictionaryConverter("EcKeyGenParams", dictEcKeyGenParams);
|
.createDictionaryConverter("EcKeyGenParams", dictEcKeyGenParams);
|
||||||
|
|
||||||
|
const dictAesKeyGenParams = [
|
||||||
|
...dictAlgorithm,
|
||||||
|
{
|
||||||
|
key: "length",
|
||||||
|
converter: (V, opts) =>
|
||||||
|
webidl.converters["unsigned short"](V, { ...opts, enforceRange: true }),
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
webidl.converters.AesKeyGenParams = webidl
|
||||||
|
.createDictionaryConverter("AesKeyGenParams", dictAesKeyGenParams);
|
||||||
|
|
||||||
const dictHmacKeyGenParams = [
|
const dictHmacKeyGenParams = [
|
||||||
...dictAlgorithm,
|
...dictAlgorithm,
|
||||||
{
|
{
|
||||||
|
|
|
@ -180,6 +180,18 @@ pub async fn op_crypto_generate_key(
|
||||||
|
|
||||||
private_key
|
private_key
|
||||||
}
|
}
|
||||||
|
Algorithm::AesCtr
|
||||||
|
| Algorithm::AesCbc
|
||||||
|
| Algorithm::AesGcm
|
||||||
|
| Algorithm::AesKw => {
|
||||||
|
let length = args.length.ok_or_else(not_supported)?;
|
||||||
|
let mut key_data = vec![0u8; length];
|
||||||
|
let rng = RingRand::SystemRandom::new();
|
||||||
|
rng.fill(&mut key_data).map_err(|_| {
|
||||||
|
custom_error("DOMExceptionOperationError", "Key generation failed")
|
||||||
|
})?;
|
||||||
|
key_data
|
||||||
|
}
|
||||||
Algorithm::Hmac => {
|
Algorithm::Hmac => {
|
||||||
let hash: HmacAlgorithm = args.hash.ok_or_else(not_supported)?.into();
|
let hash: HmacAlgorithm = args.hash.ok_or_else(not_supported)?.into();
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue