details: https://hg.nginx.org/njs/rev/873830a0a78f branches: changeset: 2132:873830a0a78f user: Dmitry Volyntsev <xei...@nginx.com> date: Tue May 23 20:58:40 2023 -0700 description: WebCrypto: introduced CryptoKey properties.
The following properties for CryptoKey were added: algorithm, extractable, type, usages. diffstat: external/njs_webcrypto_module.c | 376 +++++++++++++++++++++++++++++++++++---- test/ts/test.ts | 6 + test/webcrypto/export.t.js | 117 ++++++++++++ ts/njs_webcrypto.d.ts | 51 +++++- 4 files changed, 502 insertions(+), 48 deletions(-) diffs (751 lines): diff -r 646374a97d8c -r 873830a0a78f external/njs_webcrypto_module.c --- a/external/njs_webcrypto_module.c Mon May 22 22:48:59 2023 -0700 +++ b/external/njs_webcrypto_module.c Tue May 23 20:58:40 2023 -0700 @@ -128,6 +128,14 @@ static njs_int_t njs_ext_unwrap_key(njs_ njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t njs_ext_wrap_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); +static njs_int_t njs_key_ext_algorithm(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +static njs_int_t njs_key_ext_extractable(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +static njs_int_t njs_key_ext_type(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +static njs_int_t njs_key_ext_usages(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval); static njs_int_t njs_ext_get_random_values(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); @@ -138,16 +146,17 @@ static njs_webcrypto_key_format_t njs_ke static njs_str_t *njs_format_string(njs_webcrypto_key_format_t fmt); static njs_int_t njs_key_usage(njs_vm_t *vm, njs_value_t *value, unsigned *mask); -static njs_int_t njs_key_ops(njs_vm_t *vm, njs_opaque_value_t *retval, - unsigned mask); +static njs_int_t njs_key_ops(njs_vm_t *vm, njs_value_t *retval, unsigned mask); static njs_webcrypto_algorithm_t *njs_key_algorithm(njs_vm_t *vm, njs_value_t *value); static njs_str_t *njs_algorithm_string(njs_webcrypto_algorithm_t *algorithm); static njs_int_t njs_algorithm_hash(njs_vm_t *vm, njs_value_t *value, njs_webcrypto_hash_t *hash); +static njs_str_t *njs_algorithm_hash_name(njs_webcrypto_hash_t hash); static const EVP_MD *njs_algorithm_hash_digest(njs_webcrypto_hash_t hash); static njs_int_t njs_algorithm_curve(njs_vm_t *vm, njs_value_t *value, int *curve); +static njs_str_t *njs_algorithm_curve_name(int curve); static njs_int_t njs_webcrypto_result(njs_vm_t *vm, njs_opaque_value_t *result, njs_int_t rc, njs_value_t *retval); @@ -414,18 +423,6 @@ static njs_str_t njs_webcrypto_alg_aes_n }; -static njs_external_t njs_ext_webcrypto_crypto_key[] = { - - { - .flags = NJS_EXTERN_PROPERTY | NJS_EXTERN_SYMBOL, - .name.symbol = NJS_SYMBOL_TO_STRING_TAG, - .u.property = { - .value = "CryptoKey", - } - }, -}; - - static njs_external_t njs_ext_subtle_webcrypto[] = { { @@ -575,6 +572,55 @@ static njs_external_t njs_ext_subtle_we }; + +static njs_external_t njs_ext_webcrypto_crypto_key[] = { + + { + .flags = NJS_EXTERN_PROPERTY | NJS_EXTERN_SYMBOL, + .name.symbol = NJS_SYMBOL_TO_STRING_TAG, + .u.property = { + .value = "CryptoKey", + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("algorithm"), + .enumerable = 1, + .u.property = { + .handler = njs_key_ext_algorithm, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("extractable"), + .enumerable = 1, + .u.property = { + .handler = njs_key_ext_extractable, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("type"), + .enumerable = 1, + .u.property = { + .handler = njs_key_ext_type, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("usages"), + .enumerable = 1, + .u.property = { + .handler = njs_key_ext_usages, + } + }, +}; + + static njs_external_t njs_ext_webcrypto[] = { { @@ -633,7 +679,11 @@ static const njs_str_t string_ext = njs static const njs_str_t string_crv = njs_str("crv"); static const njs_str_t string_kty = njs_str("kty"); static const njs_str_t key_ops = njs_str("key_ops"); +static const njs_str_t string_hash = njs_str("hash"); +static const njs_str_t string_name = njs_str("name"); static const njs_str_t string_length = njs_str("length"); +static const njs_str_t string_ml = njs_str("modulusLength"); +static const njs_str_t string_curve = njs_str("namedCurve"); static njs_int_t njs_webcrypto_crypto_key_proto_id; @@ -1865,15 +1915,15 @@ njs_export_jwk_rsa(njs_vm_t *vm, njs_web static njs_int_t njs_export_jwk_ec(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) { - int nid, group_bits, group_bytes; - BIGNUM *x_bn, *y_bn; - njs_int_t ret; - const EC_KEY *ec; - const BIGNUM *d_bn; - const EC_POINT *pub; - const EC_GROUP *group; - njs_opaque_value_t xvalue, yvalue, dvalue, name, ec_s; - njs_webcrypto_entry_t *e; + int nid, group_bits, group_bytes; + BIGNUM *x_bn, *y_bn; + njs_int_t ret; + njs_str_t *cname; + const EC_KEY *ec; + const BIGNUM *d_bn; + const EC_POINT *pub; + const EC_GROUP *group; + njs_opaque_value_t xvalue, yvalue, dvalue, name, ec_s; x_bn = NULL; y_bn = NULL; @@ -1920,15 +1970,11 @@ njs_export_jwk_ec(njs_vm_t *vm, njs_webc nid = EC_GROUP_get_curve_name(group); - for (e = &njs_webcrypto_curve[0]; e->name.length != 0; e++) { - if ((uintptr_t) nid == e->value) { - (void) njs_vm_value_string_set(vm, njs_value_arg(&name), - e->name.start, e->name.length); - break; - } - } - - if (e->name.length == 0) { + cname = njs_algorithm_curve_name(nid); + (void) njs_vm_value_string_set(vm, njs_value_arg(&name), + cname->start, cname->length); + + if (cname->length == 0) { njs_vm_error(vm, "Unsupported JWK EC curve: %s", OBJ_nid2sn(nid)); goto fail; } @@ -2069,7 +2115,7 @@ njs_export_jwk_asymmetric(njs_vm_t *vm, return NJS_ERROR; } - ret = njs_key_ops(vm, &ops, key->usage); + ret = njs_key_ops(vm, njs_value_arg(&ops), key->usage); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -2124,7 +2170,7 @@ njs_export_jwk_oct(njs_vm_t *vm, njs_web } } - ret = njs_key_ops(vm, &ops, key->usage); + ret = njs_key_ops(vm, njs_value_arg(&ops), key->usage); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -2356,7 +2402,6 @@ njs_ext_generate_key(njs_vm_t *vm, njs_v njs_opaque_value_t value, pub, priv; njs_webcrypto_algorithm_t *alg; - static const njs_str_t string_ml = njs_str("modulusLength"); static const njs_str_t string_priv = njs_str("privateKey"); static const njs_str_t string_pub = njs_str("publicKey"); @@ -4076,6 +4121,225 @@ njs_ext_wrap_key(njs_vm_t *vm, njs_value static njs_int_t +njs_key_ext_algorithm(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval) +{ + u_char *start; + njs_int_t ret; + njs_str_t *name; + const BIGNUM *n_bn, *e_bn; + const EC_GROUP *group; + njs_opaque_value_t alg, name_s, val, hash; + njs_webcrypto_key_t *key; + + static const njs_str_t string_pexponent = njs_str("publicExponent"); + + key = njs_vm_external(vm, njs_webcrypto_crypto_key_proto_id, value); + if (njs_slow_path(key == NULL)) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + name = &njs_webcrypto_alg[key->alg->type].name; + ret = njs_vm_value_string_set(vm, njs_value_arg(&alg), name->start, + name->length); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + (void) njs_vm_value_string_set(vm, njs_value_arg(&name_s), + (u_char *) "name", njs_length("name")); + + ret = njs_vm_object_alloc(vm, retval, &name_s, &alg, NULL); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + switch (key->alg->type) { + case NJS_ALGORITHM_RSASSA_PKCS1_v1_5: + case NJS_ALGORITHM_RSA_PSS: + case NJS_ALGORITHM_RSA_OAEP: + /* RsaHashedKeyGenParams */ + + njs_assert(key->u.a.pkey != NULL); + njs_assert(EVP_PKEY_id(key->u.a.pkey) == EVP_PKEY_RSA); + + njs_rsa_get0_key(njs_pkey_get_rsa_key(key->u.a.pkey), &n_bn, &e_bn, + NULL); + + njs_value_number_set(njs_value_arg(&val), BN_num_bits(n_bn)); + + ret = njs_vm_object_prop_set(vm, retval, &string_ml, &val); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + start = njs_mp_alloc(njs_vm_memory_pool(vm), BN_num_bytes(e_bn)); + if (njs_slow_path(start == NULL)) { + njs_vm_memory_error(vm); + return NJS_ERROR; + } + + BN_bn2bin(e_bn, start); + + ret = njs_vm_value_buffer_set(vm, njs_value_arg(&val), start, + BN_num_bytes(e_bn)); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, retval, &string_pexponent, &val); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + name = njs_algorithm_hash_name(key->hash); + ret = njs_vm_value_string_set(vm, njs_value_arg(&hash), name->start, + name->length); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + ret = njs_vm_object_alloc(vm, njs_value_arg(&val), NULL); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, njs_value_arg(&val), &string_name, + &hash); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, retval, &string_hash, &val); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + break; + + case NJS_ALGORITHM_AES_GCM: + case NJS_ALGORITHM_AES_CTR: + case NJS_ALGORITHM_AES_CBC: + /* AesKeyGenParams */ + + njs_value_number_set(njs_value_arg(&val), key->u.s.raw.length * 8); + + ret = njs_vm_object_prop_set(vm, retval, &string_length, &val); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + break; + + case NJS_ALGORITHM_ECDSA: + case NJS_ALGORITHM_ECDH: + /* EcKeyGenParams */ + + njs_assert(key->u.a.pkey != NULL); + njs_assert(EVP_PKEY_id(key->u.a.pkey) == EVP_PKEY_EC); + + group = EC_KEY_get0_group(njs_pkey_get_ec_key(key->u.a.pkey)); + + name = njs_algorithm_curve_name(EC_GROUP_get_curve_name(group)); + + ret = njs_vm_value_string_set(vm, njs_value_arg(&val), name->start, + name->length); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, retval, &string_curve, &val); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + break; + + case NJS_ALGORITHM_HMAC: + default: + /* HmacKeyGenParams */ + + name = njs_algorithm_hash_name(key->hash); + ret = njs_vm_value_string_set(vm, njs_value_arg(&val), name->start, + name->length); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, retval, &string_hash, &val); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + break; + } + + return NJS_OK; +} + + +static njs_int_t +njs_key_ext_extractable(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + njs_webcrypto_key_t *key; + + key = njs_vm_external(vm, njs_webcrypto_crypto_key_proto_id, value); + if (njs_slow_path(key == NULL)) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + njs_value_boolean_set(retval, key->extractable); + + return NJS_OK; +} + + +static njs_int_t +njs_key_ext_type(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval) +{ + const char *type; + njs_webcrypto_key_t *key; + + key = njs_vm_external(vm, njs_webcrypto_crypto_key_proto_id, value); + if (njs_slow_path(key == NULL)) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + if (key->alg->raw) { + (void) njs_vm_value_string_set(vm, retval, (u_char *) "secret", + njs_length("secret")); + } else { + type = key->u.a.privat ? "private": "public"; + (void) njs_vm_value_string_set(vm, retval, (u_char *) type, + key->u.a.privat ? 7 : 6); + } + + return NJS_OK; +} + + +static njs_int_t +njs_key_ext_usages(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval) +{ + njs_webcrypto_key_t *key; + + key = njs_vm_external(vm, njs_webcrypto_crypto_key_proto_id, value); + if (njs_slow_path(key == NULL)) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + return njs_key_ops(vm, retval, key->usage); +} + + +static njs_int_t njs_ext_get_random_values(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { @@ -4253,20 +4517,20 @@ njs_key_usage(njs_vm_t *vm, njs_value_t static njs_int_t -njs_key_ops(njs_vm_t *vm, njs_opaque_value_t *retval, unsigned mask) +njs_key_ops(njs_vm_t *vm, njs_value_t *retval, unsigned mask) { njs_int_t ret; njs_value_t *value; njs_webcrypto_entry_t *e; - ret = njs_vm_array_alloc(vm, njs_value_arg(retval), 4); + ret = njs_vm_array_alloc(vm, retval, 4); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } for (e = &njs_webcrypto_usage[0]; e->name.length != 0; e++) { if (mask & e->value) { - value = njs_vm_array_push(vm, njs_value_arg(retval)); + value = njs_vm_array_push(vm, retval); if (value == NULL) { return NJS_ERROR; } @@ -4293,8 +4557,6 @@ njs_key_algorithm(njs_vm_t *vm, njs_valu njs_webcrypto_entry_t *e; njs_webcrypto_algorithm_t *alg; - static const njs_str_t string_name = njs_str("name"); - if (njs_value_is_object(options)) { val = njs_vm_object_prop(vm, options, &string_name, &name); if (njs_slow_path(val == NULL)) { @@ -4358,8 +4620,6 @@ njs_algorithm_hash(njs_vm_t *vm, njs_val njs_opaque_value_t value; njs_webcrypto_entry_t *e; - static const njs_str_t string_hash = njs_str("hash"); - if (njs_value_is_object(options)) { val = njs_vm_object_prop(vm, options, &string_hash, &value); if (njs_slow_path(val == NULL)) { @@ -4390,6 +4650,21 @@ njs_algorithm_hash(njs_vm_t *vm, njs_val } +static njs_str_t * +njs_algorithm_hash_name(njs_webcrypto_hash_t hash) +{ + njs_webcrypto_entry_t *e; + + for (e = &njs_webcrypto_hash[0]; e->name.length != 0; e++) { + if (e->value == hash) { + return &e->name; + } + } + + return &e->name; +} + + static const EVP_MD * njs_algorithm_hash_digest(njs_webcrypto_hash_t hash) { @@ -4421,8 +4696,6 @@ njs_algorithm_curve(njs_vm_t *vm, njs_va njs_opaque_value_t value; njs_webcrypto_entry_t *e; - static const njs_str_t string_curve = njs_str("namedCurve"); - if (*curve != 0) { return NJS_OK; } @@ -4452,6 +4725,21 @@ njs_algorithm_curve(njs_vm_t *vm, njs_va } +static njs_str_t * +njs_algorithm_curve_name(int curve) +{ + njs_webcrypto_entry_t *e; + + for (e = &njs_webcrypto_curve[0]; e->name.length != 0; e++) { + if (e->value == (uintptr_t) curve) { + return &e->name; + } + } + + return &e->name; +} + + static njs_int_t njs_promise_trampoline(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) diff -r 646374a97d8c -r 873830a0a78f test/ts/test.ts --- a/test/ts/test.ts Mon May 22 22:48:59 2023 -0700 +++ b/test/ts/test.ts Tue May 23 20:58:40 2023 -0700 @@ -246,13 +246,19 @@ async function crypto_object(keyData: Ar publicExponent: new Uint8Array([1, 0, 1])}, true, ['sign', 'verify']); + pair.privateKey.extractable; + pair.publicKey.algorithm.name; + let hkey = await crypto.subtle.generateKey({name: "HMAC", hash: "SHA-384"}, true, ['sign', 'verify']); + hkey.algorithm.name; let akey = await crypto.subtle.generateKey({name: "AES-GCM", length: 256}, true, ['encrypt', 'decrypt']); + + akey.type; } function buffer(b: Buffer) { diff -r 646374a97d8c -r 873830a0a78f test/webcrypto/export.t.js --- a/test/webcrypto/export.t.js Mon May 22 22:48:59 2023 -0700 +++ b/test/webcrypto/export.t.js Tue May 23 20:58:40 2023 -0700 @@ -35,6 +35,8 @@ async function test(params) { let key = await load_key(params); let exp = await crypto.subtle.exportKey(params.export.fmt, key); + validate_key(key, params); + if (params.check && !params.check(exp, params)) { throw Error(`failed check`); } @@ -92,6 +94,121 @@ function p(args, default_opts) { return params; } +function validate_key(key, params) { + let opts; + + if (params.generate_keys) { + opts = params.generate_keys; + + } else if (params.generate_key) { + opts = params.generate_key; + + } else { + opts = params.key; + } + + if (opts.extractable != key.extractable) { + throw Error(`unexpected generated key.extractable: ${key.extractable}`); + } + + switch (key.type) { + case "secret": + /* AesKeyGenParams */ + + switch (key.algorithm.name) { + case "AES-CBC": + case "AES-CTR": + case "AES-GCM": + let length = key.algorithm.length; + + switch (length) { + case 128: + case 192: + case 256: + break; + default: + throw Error(`unexpected symmetric generated key.algorithm.length: ${length}`); + } + + /* FALLTHROUGH */ + + case "HMAC": + if (!compareObjects(opts.usage, key.usages)) { + throw Error(`unexpected symmetric generated key.usages: ${key.usages}`); + } + + break; + + default: + throw Error(`unexpected symmetric generated key.algorithm.name: ${key.algorithm.name}`); + } + + break; + case "private": + case "public": + if (opts.expected && !compareObjects(opts.expected.key_ops, key.usages)) { + throw Error(`unexpected asymmetric generated key.usages: ${key.usages}`); + } + + switch (key.algorithm.name) { + case "RSA-OAEP": + case "RSA-PSS": + case "RSASSA-PKCS1-v1_5": + /* RsaHashedKeyGenParams */ + + let mlength = key.algorithm.modulusLength; + let pexp = key.algorithm.publicExponent; + let hash = key.algorithm.hash.name; + + switch (mlength) { + case 1024: + case 2048: + case 4096: + break; + default: + throw Error(`unexpected asymmetric generated key.algorithm.modulusLength: ${mlength}`); + } + + if (!compareObjects(new Uint8Array([1, 0, 1]), pexp)) { + throw Error(`unexpected asymmetric generated key.algorithm.publicExponent: ${pexp}`); + } + + switch (hash) { + case "SHA-1": + case "SHA-256": + case "SHA-384": + case "SHA-512": + break; + default: + throw Error(`unexpected asymmetric generated key.algorithm.hash.name: ${hash}`); + } + + break; + case "ECDSA": + case "ECDH": + /* EcKeyGenParams */ + + let crv = key.algorithm.namedCurve; + switch (crv) { + case "P-256": + case "P-384": + case "P-521": + break; + default: + throw Error(`unexpected asymmetric generated key.algorithm.namedCurve: ${crv}`); + } + + break; + default: + throw Error(`unexpected asymmetric generated key.algorithm.name: ${key.algorithm.name}`); + } + + break; + default: + throw Error(`unexpected generated key.type: ${key.type}`); + } +} + function validate_property(exp, p, exp_len) { if (!exp[p]) { throw Error(`"${p}" is not found in ${JSON.stringify(exp)}`); diff -r 646374a97d8c -r 873830a0a78f ts/njs_webcrypto.d.ts --- a/ts/njs_webcrypto.d.ts Mon May 22 22:48:59 2023 -0700 +++ b/ts/njs_webcrypto.d.ts Tue May 23 20:58:40 2023 -0700 @@ -136,6 +136,35 @@ type SignOrVerifyAlgorithm = | "RSASSA-PKCS1-v1_5"; interface CryptoKey { + /* + * An object describing the algorithm for which this key can be used + * and any associated extra parameters. + * @since 0.8.0 + */ + readonly algorithm: GenerateAlgorithm; + /* + * A boolean value that is true if the key can be exported and false if not. + * @since 0.8.0 + */ + readonly extractable: boolean; + /* + * A string value indicates which kind of key is represented by the object. + * + * It can have the following values: + * "secret": This key is a secret key for use with a symmetric algorithm. + * "private": This key is the private half of an asymmetric algorithm's CryptoKeyPair. + * "public": This key is the public half of an asymmetric algorithm's CryptoKeyPair. + * @since 0.8.0 + */ + readonly type: string; + + /* + * An array of strings indicating what this key can be used for. + * Possible array values: "encrypt", "decrypt", "sign", "verify", + * "deriveKey", "deriveBits", "wrapKey", "unwrapKey". + * @since 0.8.0 + */ + readonly usages: Array<string>; } type CryptoKeyPair = { privateKey: CryptoKey, publicKey: CryptoKey }; @@ -233,8 +262,7 @@ interface SubtleCrypto { key: CryptoKey): Promise<ArrayBuffer|Object>; /** - * Generates a key for symmetric algorithms or a keypair - * for asymmetric algorithms. + * Generates a key for symmetric algorithms. * * @since 0.7.10 * @param algorithm Dictionary object defining the type of key to generate @@ -244,9 +272,24 @@ interface SubtleCrypto { * Possible array values: "encrypt", "decrypt", "sign", "verify", * "deriveKey", "deriveBits", "wrapKey", "unwrapKey". */ - generateKey(algorithm: GenerateAlgorithm, + generateKey(algorithm: HmacKeyGenParams | AesKeyGenParams, extractable: boolean, - usage: Array<string>): Promise<CryptoKey|CryptoKeyPair>; + usage: Array<string>): Promise<CryptoKey>; + + /** + * Generates a key for asymmetric algorithms. + * + * @since 0.7.10 + * @param algorithm Dictionary object defining the type of key to generate + * and providing extra algorithm-specific parameters. + * @param extractable Boolean indicating whether a key can be exported. + * @param usage Array indicating what can be done with the key. + * Possible array values: "encrypt", "decrypt", "sign", "verify", + * "deriveKey", "deriveBits", "wrapKey", "unwrapKey". + */ + generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, + extractable: boolean, + usage: Array<string>): Promise<CryptoKeyPair>; /** * Generates a digital signature. _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel