Welcome! Log In Create A New Profile

Advanced

[njs] WebCrypto: introduced CryptoKey properties.

Dmitry Volyntsev
May 24, 2023 12:22AM
details: https://hg.nginx.org/njs/rev/873830a0a78f
branches:
changeset: 2132:873830a0a78f
user: Dmitry Volyntsev <xeioex@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
Subject Author Views Posted

[njs] WebCrypto: introduced CryptoKey properties.

Dmitry Volyntsev 256 May 24, 2023 12:22AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 292
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready