1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-24 08:09:08 -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:
Luca Casonato 2021-08-31 11:25:44 +02:00 committed by GitHub
parent fcd0992dba
commit cee5be4539
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 107 additions and 1414 deletions

View file

@ -77,6 +77,10 @@
"RSA-PSS": "RsaHashedKeyGenParams",
"RSA-OAEP": "RsaHashedKeyGenParams",
"ECDSA": "EcKeyGenParams",
"AES-CTR": "AesKeyGenParams",
"AES-CBC": "AesKeyGenParams",
"AES-GCM": "AesKeyGenParams",
"AES-KW": "AesKeyGenParams",
"HMAC": "HmacKeyGenParams",
},
"sign": {
@ -1415,10 +1419,40 @@
return { publicKey, privateKey };
}
// TODO(lucacasonato): ECDH
// TODO(lucacasonato): AES-CTR
// TODO(lucacasonato): AES-CBC
// TODO(lucacasonato): AES-GCM
// TODO(lucacasonato): AES-KW
case "AES-CTR":
case "AES-CBC":
case "AES-GCM": {
// 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": {
// 1.
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) {
switch (normalizedAlgorithm.name) {
case "PBKDF2": {

View file

@ -117,6 +117,19 @@
webidl.converters.EcKeyGenParams = webidl
.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 = [
...dictAlgorithm,
{

View file

@ -180,6 +180,18 @@ pub async fn op_crypto_generate_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 => {
let hash: HmacAlgorithm = args.hash.ok_or_else(not_supported)?.into();

File diff suppressed because it is too large Load diff