From: Dmitry Volyntsev Date: Tue, 22 Sep 2020 18:42:21 +0000 (+0000) Subject: Adding support for Buffer objects in crypto methods. X-Git-Tag: 0.4.4~4 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=2b05aaec3e5771796f3858be1c66bf98430296de;p=njs.git Adding support for Buffer objects in crypto methods. --- diff --git a/src/njs_buffer.c b/src/njs_buffer.c index d71fa1dd..0996f656 100644 --- a/src/njs_buffer.c +++ b/src/njs_buffer.c @@ -17,19 +17,6 @@ ((size << 2) | (sign << 1) | little) -typedef njs_int_t (*njs_buffer_encode)(njs_vm_t *vm, njs_value_t *value, - const njs_str_t *src); -typedef size_t (*njs_buffer_encode_length)(const njs_str_t *src, - size_t *out_size); - -typedef struct { - njs_str_t name; - njs_buffer_encode encode; - njs_buffer_encode decode; - njs_buffer_encode_length decode_length; -} njs_buffer_encoding_t; - - static njs_buffer_encoding_t njs_buffer_encodings[] = { { @@ -83,18 +70,15 @@ static njs_int_t njs_buffer_write_string(njs_vm_t *vm, njs_value_t *value, njs_typed_array_t *array, const njs_buffer_encoding_t *encoding, uint64_t offset, uint64_t length); static njs_int_t njs_buffer_fill(njs_vm_t *vm, njs_typed_array_t *array, - njs_value_t *value, const njs_buffer_encoding_t *encoding, uint64_t offset, + const njs_value_t *fill, const njs_value_t *encoding, uint64_t offset, uint64_t end); -static njs_int_t njs_buffer_fill_string(njs_vm_t *vm, njs_value_t *value, +static njs_int_t njs_buffer_fill_string(njs_vm_t *vm, const njs_value_t *value, njs_typed_array_t *array, const njs_buffer_encoding_t *encoding, uint8_t *start, uint8_t *end); -static njs_int_t njs_buffer_fill_typed_array(njs_vm_t *vm, njs_value_t *value, - njs_typed_array_t *array, uint8_t *start, uint8_t *end); -static const njs_buffer_encoding_t *njs_buffer_encoding(njs_vm_t *vm, - njs_value_t *value); -static njs_int_t njs_buffer_decode_string(njs_vm_t *vm, njs_value_t *value, - njs_value_t *dst, const njs_buffer_encoding_t *encoding); -static void njs_buffer_decode_destroy(njs_vm_t *vm, njs_value_t *source, +static njs_int_t njs_buffer_fill_typed_array(njs_vm_t *vm, + const njs_value_t *value, njs_typed_array_t *array, uint8_t *start, + uint8_t *end); +static void njs_buffer_decode_destroy(njs_vm_t *vm, const njs_value_t *source, njs_value_t *target); @@ -149,8 +133,8 @@ njs_buffer_set(njs_vm_t *vm, njs_value_t *value, const u_char *start, } -static njs_typed_array_t * -njs_buffer_alloc_array(njs_vm_t *vm, size_t size, njs_bool_t zeroing) +njs_typed_array_t * +njs_buffer_alloc(njs_vm_t *vm, size_t size, njs_bool_t zeroing) { njs_value_t value; njs_typed_array_t *array; @@ -169,6 +153,25 @@ njs_buffer_alloc_array(njs_vm_t *vm, size_t size, njs_bool_t zeroing) } +njs_int_t +njs_buffer_new(njs_vm_t *vm, njs_value_t *value, const u_char *start, + uint32_t size) +{ + njs_typed_array_t *buffer; + + buffer = njs_buffer_alloc(vm, size, 0); + if (njs_slow_path(buffer == NULL)) { + return NJS_ERROR; + } + + memcpy(njs_typed_array_buffer(buffer)->u.u8, start, size); + + njs_set_typed_array(value, buffer); + + return NJS_OK; +} + + static njs_int_t njs_buffer_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) @@ -180,13 +183,13 @@ njs_buffer_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t -njs_buffer_alloc(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, +njs_buffer_alloc_safe(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t safe) { - double size; - njs_int_t ret; - njs_typed_array_t *array; - const njs_buffer_encoding_t *encoding; + double size; + njs_int_t ret; + njs_typed_array_t *array; + const njs_value_t *fill; if (njs_slow_path(!njs_is_number(njs_arg(args, nargs, 1)))) { njs_type_error(vm, "\"size\" argument must be of type number"); @@ -199,22 +202,15 @@ njs_buffer_alloc(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - array = njs_buffer_alloc_array(vm, size, safe || nargs <= 2); + array = njs_buffer_alloc(vm, size, safe || nargs <= 2); if (njs_slow_path(array == NULL)) { return NJS_ERROR; } - if (safe && nargs > 2) { - encoding = njs_buffer_utf8_encoding(); - - if (nargs > 3 && njs_is_string(njs_argument(args, 2))) { - encoding = njs_buffer_encoding(vm, njs_argument(args, 3)); - if (njs_slow_path(encoding == NULL)) { - return NJS_ERROR; - } - } + fill = njs_arg(args, nargs, 2); - ret = njs_buffer_fill(vm, array, njs_argument(args, 2), encoding, 0, + if (safe && njs_is_defined(fill)) { + ret = njs_buffer_fill(vm, array, fill, njs_arg(args, nargs, 3), 0, array->byte_length); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; @@ -246,13 +242,9 @@ njs_buffer_from(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_arg(args, nargs, 3)); case NJS_STRING: - encoding = njs_buffer_utf8_encoding(); - - if (nargs > 2) { - encoding = njs_buffer_encoding(vm, njs_argument(args, 2)); - if (njs_slow_path(encoding == NULL)) { - return NJS_ERROR; - } + encoding = njs_buffer_encoding(vm, njs_arg(args, nargs, 2)); + if (njs_slow_path(encoding == NULL)) { + return NJS_ERROR; } return njs_buffer_from_string(vm, value, encoding); @@ -334,7 +326,7 @@ next: return ret; } - buffer = njs_buffer_alloc_array(vm, len, 0); + buffer = njs_buffer_alloc(vm, len, 0); if (njs_slow_path(buffer == NULL)) { return NJS_ERROR; } @@ -448,7 +440,7 @@ njs_buffer_from_typed_array(njs_vm_t *vm, njs_value_t *value) length = njs_typed_array_length(array); - buffer = njs_buffer_alloc_array(vm, length, 0); + buffer = njs_buffer_alloc(vm, length, 0); if (njs_slow_path(buffer == NULL)) { return NJS_ERROR; } @@ -481,7 +473,7 @@ njs_buffer_from_string(njs_vm_t *vm, njs_value_t *value, njs_string_get(&dst, &str); - buffer = njs_buffer_alloc_array(vm, str.length, 0); + buffer = njs_buffer_alloc(vm, str.length, 0); if (njs_slow_path(buffer == NULL)) { return NJS_ERROR; } @@ -812,7 +804,7 @@ njs_buffer_concat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - buffer = njs_buffer_alloc_array(vm, len, 0); + buffer = njs_buffer_alloc(vm, len, 0); if (njs_slow_path(buffer == NULL)) { return NJS_ERROR; } @@ -884,8 +876,11 @@ static njs_int_t njs_buffer_is_encoding(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_set_boolean(&vm->retval, - njs_buffer_encoding(vm, njs_arg(args, nargs, 1)) != NULL); + const njs_value_t *value; + + value = njs_arg(args, nargs, 1); + njs_set_boolean(&vm->retval, njs_is_defined(value) + && njs_buffer_encoding(vm, value) != NULL); return NJS_OK; } @@ -1563,12 +1558,11 @@ static njs_int_t njs_buffer_prototype_fill(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - uint64_t offset, end; - njs_int_t ret; - njs_value_t *this, *value, *value_offset, *value_end, - *encode; - njs_typed_array_t *array; - const njs_buffer_encoding_t *encoding; + uint64_t offset, end; + njs_int_t ret; + njs_value_t *this, *value, *value_offset, *value_end, + *encode; + njs_typed_array_t *array; this = njs_argument(args, 0); if (njs_slow_path(nargs < 2)) { @@ -1584,8 +1578,6 @@ njs_buffer_prototype_fill(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, value_offset = njs_arg(args, nargs, 2); value_end = njs_arg(args, nargs, 3); encode = njs_arg(args, nargs, 4); - encoding = njs_buffer_utf8_encoding(); - offset = 0; end = array->byte_length; @@ -1593,7 +1585,7 @@ njs_buffer_prototype_fill(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, if (njs_is_defined(value_offset)) { if (njs_is_string(value) && njs_is_string(value_offset)) { encode = value_offset; - goto encoding; + goto fill; } ret = njs_value_to_index(vm, value_offset, &offset); @@ -1605,7 +1597,7 @@ njs_buffer_prototype_fill(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, if (njs_is_defined(value_end)) { if (njs_is_string(value) && njs_is_string(value_end)) { encode = value_end; - goto encoding; + goto fill; } ret = njs_value_to_index(vm, value_end, &end); @@ -1614,21 +1606,9 @@ njs_buffer_prototype_fill(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - if (njs_is_defined(encode)) { - if (njs_slow_path(!njs_is_string(encode))) { - njs_type_error(vm, "\"encoding\" argument must be of type string"); - return NJS_ERROR; - } - - encoding: - - encoding = njs_buffer_encoding(vm, encode); - if (njs_slow_path(encoding == NULL)) { - return NJS_ERROR; - } - } +fill: - ret = njs_buffer_fill(vm, array, value, encoding, offset, end); + ret = njs_buffer_fill(vm, array, value, encode, offset, end); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -1642,13 +1622,14 @@ done: static njs_int_t -njs_buffer_fill(njs_vm_t *vm, njs_typed_array_t *array, njs_value_t *value, - const njs_buffer_encoding_t *encoding, uint64_t offset, uint64_t end) +njs_buffer_fill(njs_vm_t *vm, njs_typed_array_t *array, const njs_value_t *fill, + const njs_value_t *encode, uint64_t offset, uint64_t end) { - double num; - uint8_t *start, *stop; - njs_int_t ret; - njs_array_buffer_t *buffer; + double num; + uint8_t *start, *stop; + njs_int_t ret; + njs_array_buffer_t *buffer; + const njs_buffer_encoding_t *encoding; buffer = njs_typed_array_writable(vm, array); if (njs_slow_path(buffer == NULL)) { @@ -1672,15 +1653,20 @@ njs_buffer_fill(njs_vm_t *vm, njs_typed_array_t *array, njs_value_t *value, start = &buffer->u.u8[array->offset + offset]; stop = &buffer->u.u8[array->offset + end]; - switch (value->type) { + switch (fill->type) { case NJS_STRING: - return njs_buffer_fill_string(vm, value, array, encoding, start, stop); + encoding = njs_buffer_encoding(vm, encode); + if (njs_slow_path(encoding == NULL)) { + return NJS_ERROR; + } + + return njs_buffer_fill_string(vm, fill, array, encoding, start, stop); case NJS_TYPED_ARRAY: - return njs_buffer_fill_typed_array(vm, value, array, start, stop); + return njs_buffer_fill_typed_array(vm, fill, array, start, stop); default: - ret = njs_value_to_number(vm, value, &num); + ret = njs_value_to_number(vm, njs_value_arg(fill), &num); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -1698,7 +1684,7 @@ njs_buffer_fill(njs_vm_t *vm, njs_typed_array_t *array, njs_value_t *value, static njs_int_t -njs_buffer_fill_string(njs_vm_t *vm, njs_value_t *value, +njs_buffer_fill_string(njs_vm_t *vm, const njs_value_t *value, njs_typed_array_t *array, const njs_buffer_encoding_t *encoding, uint8_t *start, uint8_t *end) { @@ -1733,7 +1719,7 @@ done: static njs_int_t -njs_buffer_fill_typed_array(njs_vm_t *vm, njs_value_t *value, +njs_buffer_fill_typed_array(njs_vm_t *vm, const njs_value_t *value, njs_typed_array_t *array, uint8_t *to, uint8_t *end) { size_t byte_length; @@ -1773,7 +1759,7 @@ njs_buffer_prototype_to_string(njs_vm_t *vm, njs_value_t *args, uint64_t start, end; njs_int_t ret; njs_str_t str; - njs_value_t *this, *enc, *value_start, *value_end; + njs_value_t *this, *value_start, *value_end; njs_typed_array_t *array; const njs_buffer_encoding_t *encoding; @@ -1783,7 +1769,6 @@ njs_buffer_prototype_to_string(njs_vm_t *vm, njs_value_t *args, return NJS_ERROR; } - enc = njs_arg(args, nargs, 1); value_start = njs_arg(args, nargs, 2); value_end = njs_arg(args, nargs, 3); @@ -1791,11 +1776,9 @@ njs_buffer_prototype_to_string(njs_vm_t *vm, njs_value_t *args, end = array->byte_length; encoding = njs_buffer_utf8_encoding(); - if (njs_is_defined(enc)) { - encoding = njs_buffer_encoding(vm, njs_argument(args, 1)); - if (njs_slow_path(encoding == NULL)) { - return NJS_ERROR; - } + encoding = njs_buffer_encoding(vm, njs_arg(args, nargs, 1)); + if (njs_slow_path(encoding == NULL)) { + return NJS_ERROR; } if (njs_is_defined(value_start)) { @@ -2265,40 +2248,41 @@ njs_buffer_prototype_to_json(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static const njs_buffer_encoding_t * -njs_buffer_encoding(njs_vm_t *vm, njs_value_t *value) +const njs_buffer_encoding_t * +njs_buffer_encoding(njs_vm_t *vm, const njs_value_t *value) { - njs_str_t str; - njs_int_t ret; + njs_str_t name; njs_buffer_encoding_t *encoding; if (njs_slow_path(!njs_is_string(value))) { - ret = njs_value_to_string(vm, value, value); - if (njs_slow_path(ret != NJS_OK)) { + if (njs_is_defined(value)) { + njs_type_error(vm, "encoding must be a string"); return NULL; } + + return &njs_buffer_encodings[0]; } - njs_string_get(value, &str); + njs_string_get(value, &name); for (encoding = &njs_buffer_encodings[0]; encoding->name.length != 0; encoding++) { - if (njs_strstr_eq(&str, &encoding->name)) { + if (njs_strstr_eq(&name, &encoding->name)) { return encoding; } } - njs_type_error(vm, "\"%V\" encoding is not supported", &str); + njs_type_error(vm, "\"%V\" encoding is not supported", &name); return NULL; } -static njs_int_t -njs_buffer_decode_string(njs_vm_t *vm, njs_value_t *value, njs_value_t *dst, - const njs_buffer_encoding_t *encoding) +njs_int_t +njs_buffer_decode_string(njs_vm_t *vm, const njs_value_t *value, + njs_value_t *dst, const njs_buffer_encoding_t *encoding) { njs_int_t ret; njs_str_t str; @@ -2325,7 +2309,7 @@ njs_buffer_decode_string(njs_vm_t *vm, njs_value_t *value, njs_value_t *dst, static void -njs_buffer_decode_destroy(njs_vm_t *vm, njs_value_t *source, +njs_buffer_decode_destroy(njs_vm_t *vm, const njs_value_t *source, njs_value_t *target) { njs_str_t src, trg; @@ -2833,7 +2817,7 @@ static const njs_object_prop_t njs_buffer_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("alloc"), - .value = njs_native_function2(njs_buffer_alloc, 0, 1), + .value = njs_native_function2(njs_buffer_alloc_safe, 0, 1), .writable = 1, .configurable = 1, }, @@ -2841,7 +2825,7 @@ static const njs_object_prop_t njs_buffer_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_string("allocUnsafe"), - .value = njs_native_function2(njs_buffer_alloc, 1, 0), + .value = njs_native_function2(njs_buffer_alloc_safe, 1, 0), .writable = 1, .configurable = 1, }, @@ -2849,7 +2833,7 @@ static const njs_object_prop_t njs_buffer_constructor_properties[] = { .type = NJS_PROPERTY, .name = njs_long_string("allocUnsafeSlow"), - .value = njs_native_function2(njs_buffer_alloc, 1, 0), + .value = njs_native_function2(njs_buffer_alloc_safe, 1, 0), .writable = 1, .configurable = 1, }, diff --git a/src/njs_buffer.h b/src/njs_buffer.h index e9b94a68..4633ebe1 100644 --- a/src/njs_buffer.h +++ b/src/njs_buffer.h @@ -8,8 +8,30 @@ #define _NJS_BUFFER_H_INCLUDED_ +typedef njs_int_t (*njs_buffer_encode_t)(njs_vm_t *vm, njs_value_t *value, + const njs_str_t *src); +typedef size_t (*njs_buffer_encode_length_t)(const njs_str_t *src, + size_t *out_size); + +typedef struct { + njs_str_t name; + njs_buffer_encode_t encode; + njs_buffer_encode_t decode; + njs_buffer_encode_length_t decode_length; +} njs_buffer_encoding_t; + + njs_int_t njs_buffer_set(njs_vm_t *vm, njs_value_t *value, const u_char *start, uint32_t size); +njs_int_t njs_buffer_new(njs_vm_t *vm, njs_value_t *value, const u_char *start, + uint32_t size); +njs_typed_array_t *njs_buffer_alloc(njs_vm_t *vm, size_t size, + njs_bool_t zeroing); + +const njs_buffer_encoding_t *njs_buffer_encoding(njs_vm_t *vm, + const njs_value_t *value); +njs_int_t njs_buffer_decode_string(njs_vm_t *vm, const njs_value_t *value, + njs_value_t *dst, const njs_buffer_encoding_t *encoding); extern const njs_object_type_init_t njs_buffer_type_init; diff --git a/src/njs_crypto.c b/src/njs_crypto.c index 71e2d0b8..9a3d3846 100644 --- a/src/njs_crypto.c +++ b/src/njs_crypto.c @@ -56,6 +56,14 @@ typedef struct { } njs_crypto_enc_t; +static njs_hash_alg_t *njs_crypto_algorithm(njs_vm_t *vm, + const njs_value_t *value); +static njs_crypto_enc_t *njs_crypto_encoding(njs_vm_t *vm, + const njs_value_t *value); +static njs_int_t njs_buffer_digest(njs_vm_t *vm, njs_value_t *value, + const njs_str_t *src); + + static njs_hash_alg_t njs_hash_algorithms[] = { { @@ -92,8 +100,14 @@ static njs_hash_alg_t njs_hash_algorithms[] = { }; + static njs_crypto_enc_t njs_encodings[] = { + { + njs_str("buffer"), + njs_buffer_digest + }, + { njs_str("hex"), njs_string_hex @@ -116,11 +130,6 @@ static njs_crypto_enc_t njs_encodings[] = { }; -static njs_hash_alg_t *njs_crypto_alg(njs_vm_t *vm, const njs_str_t *name); -static njs_crypto_enc_t *njs_crypto_encoding(njs_vm_t *vm, - const njs_str_t *name); - - static njs_object_value_t * njs_crypto_object_value_alloc(njs_vm_t *vm, njs_object_type_t type) { @@ -152,19 +161,11 @@ static njs_int_t njs_crypto_create_hash(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_str_t alg_name; njs_digest_t *dgst; njs_hash_alg_t *alg; njs_object_value_t *hash; - if (njs_slow_path(nargs < 2 || !njs_is_string(&args[1]))) { - njs_type_error(vm, "algorithm must be a string"); - return NJS_ERROR; - } - - njs_string_get(&args[1], &alg_name); - - alg = njs_crypto_alg(vm, &alg_name); + alg = njs_crypto_algorithm(vm, njs_arg(args, nargs, 1)); if (njs_slow_path(alg == NULL)) { return NJS_ERROR; } @@ -193,34 +194,79 @@ njs_crypto_create_hash(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t njs_hash_prototype_update(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) + njs_index_t tag) { - njs_str_t data; - njs_value_t *this; - njs_digest_t *dgst; - - if (njs_slow_path(nargs < 2 || !njs_is_string(&args[1]))) { - njs_type_error(vm, "data must be a string"); - return NJS_ERROR; - } + njs_str_t data; + njs_int_t ret; + njs_hmac_t *ctx; + njs_value_t *this, dst; + njs_digest_t *dgst; + njs_typed_array_t *array; + const njs_value_t *value; + njs_array_buffer_t *buffer; + const njs_buffer_encoding_t *encoding; this = njs_argument(args, 0); - - if (njs_slow_path(!njs_is_object_data(this, NJS_DATA_TAG_CRYPTO_HASH))) { + if (njs_slow_path(!njs_is_object_data(this, tag))) { njs_type_error(vm, "\"this\" is not a hash object"); return NJS_ERROR; } - njs_string_get(&args[1], &data); + value = njs_arg(args, nargs, 1); - dgst = njs_object_data(this); + switch (value->type) { + case NJS_STRING: + encoding = njs_buffer_encoding(vm, njs_arg(args, nargs, 2)); + if (njs_slow_path(encoding == NULL)) { + return NJS_ERROR; + } + + ret = njs_buffer_decode_string(vm, value, &dst, encoding); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + njs_string_get(&dst, &data); + break; + + case NJS_TYPED_ARRAY: + case NJS_DATA_VIEW: + array = njs_typed_array(value); + buffer = array->buffer; + if (njs_slow_path(njs_is_detached_buffer(buffer))) { + njs_type_error(vm, "detached buffer"); + return NJS_ERROR; + } + + data.start = &buffer->u.u8[array->offset]; + data.length = array->byte_length; + break; + + default: + njs_type_error(vm, "data argument \"%s\" is not a string " + "or Buffer-like object", njs_type_string(value->type)); - if (njs_slow_path(dgst->alg == NULL)) { - njs_error(vm, "Digest already called"); return NJS_ERROR; } - dgst->alg->update(&dgst->u, data.start, data.length); + if (tag == NJS_DATA_TAG_CRYPTO_HASH) { + dgst = njs_object_data(this); + if (njs_slow_path(dgst->alg == NULL)) { + njs_error(vm, "Digest already called"); + return NJS_ERROR; + } + + dgst->alg->update(&dgst->u, data.start, data.length); + + } else { + ctx = njs_object_data(this); + if (njs_slow_path(ctx->alg == NULL)) { + njs_error(vm, "Digest already called"); + return NJS_ERROR; + } + + ctx->alg->update(&ctx->u, data.start, data.length); + } vm->retval = *this; @@ -230,71 +276,62 @@ njs_hash_prototype_update(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_int_t njs_hash_prototype_digest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) + njs_index_t tag) { - u_char digest[32], *p; - njs_int_t ret; - njs_str_t enc_name, str; + njs_str_t str; + njs_hmac_t *ctx; njs_value_t *this; njs_digest_t *dgst; njs_hash_alg_t *alg; njs_crypto_enc_t *enc; + u_char hash1[32], digest[32]; - if (njs_slow_path(nargs > 1 && !njs_is_string(&args[1]))) { - njs_type_error(vm, "encoding must be a string"); + this = njs_argument(args, 0); + if (njs_slow_path(!njs_is_object_data(this, tag))) { + njs_type_error(vm, "\"this\" is not a hash object"); return NJS_ERROR; } - this = njs_argument(args, 0); - - if (njs_slow_path(!njs_is_object_data(this, NJS_DATA_TAG_CRYPTO_HASH))) { - njs_type_error(vm, "\"this\" is not a hash object"); + enc = njs_crypto_encoding(vm, njs_arg(args, nargs, 1)); + if (njs_slow_path(enc == NULL)) { return NJS_ERROR; } - enc = NULL; + if (tag == NJS_DATA_TAG_CRYPTO_HASH) { + dgst = njs_object_data(this); + if (njs_slow_path(dgst->alg == NULL)) { + goto exception; + } - if (nargs > 1) { - njs_string_get(&args[1], &enc_name); + alg = dgst->alg; + alg->final(digest, &dgst->u); + dgst->alg = NULL; - enc = njs_crypto_encoding(vm, &enc_name); - if (njs_slow_path(enc == NULL)) { - return NJS_ERROR; + } else { + ctx = njs_object_data(this); + if (njs_slow_path(ctx->alg == NULL)) { + goto exception; } - } - dgst = njs_object_data(this); + alg = ctx->alg; + alg->final(hash1, &ctx->u); - if (njs_slow_path(dgst->alg == NULL)) { - njs_error(vm, "Digest already called"); - return NJS_ERROR; + alg->init(&ctx->u); + alg->update(&ctx->u, ctx->opad, 64); + alg->update(&ctx->u, hash1, alg->size); + alg->final(digest, &ctx->u); + ctx->alg = NULL; } - alg = dgst->alg; - - alg->final(digest, &dgst->u); - str.start = digest; str.length = alg->size; - if (enc == NULL) { - p = njs_string_alloc(vm, &vm->retval, str.length, 0); - - if (njs_fast_path(p != NULL)) { - memcpy(p, str.start, str.length); - ret = NJS_OK; - - } else { - ret = NJS_ERROR; - } - - } else { - ret = enc->encode(vm, &vm->retval, &str); - } + return enc->encode(vm, &vm->retval, &str); - dgst->alg = NULL; +exception: - return ret; + njs_error(vm, "Digest already called"); + return NJS_ERROR; } @@ -317,7 +354,8 @@ static const njs_object_prop_t njs_hash_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("update"), - .value = njs_native_function(njs_hash_prototype_update, 0), + .value = njs_native_function2(njs_hash_prototype_update, 0, + NJS_DATA_TAG_CRYPTO_HASH), .writable = 1, .configurable = 1, }, @@ -325,7 +363,8 @@ static const njs_object_prop_t njs_hash_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("digest"), - .value = njs_native_function(njs_hash_prototype_digest, 0), + .value = njs_native_function2(njs_hash_prototype_digest, 0, + NJS_DATA_TAG_CRYPTO_HASH), .writable = 1, .configurable = 1, }, @@ -397,32 +436,48 @@ static njs_int_t njs_crypto_create_hmac(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - u_char digest[32], key_buf[64]; - njs_str_t alg_name, key; + njs_str_t key; njs_uint_t i; njs_hmac_t *ctx; njs_hash_alg_t *alg; + njs_typed_array_t *array; + const njs_value_t *value; + njs_array_buffer_t *buffer; njs_object_value_t *hmac; + u_char digest[32], key_buf[64]; - if (njs_slow_path(nargs < 2 || !njs_is_string(&args[1]))) { - njs_type_error(vm, "algorithm must be a string"); + alg = njs_crypto_algorithm(vm, njs_arg(args, nargs, 1)); + if (njs_slow_path(alg == NULL)) { return NJS_ERROR; } - if (njs_slow_path(nargs < 3 || !njs_is_string(&args[2]))) { - njs_type_error(vm, "key must be a string"); - return NJS_ERROR; - } + value = njs_arg(args, nargs, 2); - njs_string_get(&args[1], &alg_name); + switch (value->type) { + case NJS_STRING: + njs_string_get(value, &key); + break; + + case NJS_TYPED_ARRAY: + case NJS_DATA_VIEW: + array = njs_typed_array(value); + buffer = array->buffer; + if (njs_slow_path(njs_is_detached_buffer(buffer))) { + njs_type_error(vm, "detached buffer"); + return NJS_ERROR; + } + + key.start = &buffer->u.u8[array->offset]; + key.length = array->byte_length; + break; + + default: + njs_type_error(vm, "key argument \"%s\" is not a string " + "or Buffer-like object", njs_type_string(value->type)); - alg = njs_crypto_alg(vm, &alg_name); - if (njs_slow_path(alg == NULL)) { return NJS_ERROR; } - njs_string_get(&args[2], &key); - ctx = njs_mp_alloc(vm->mem_pool, sizeof(njs_hmac_t)); if (njs_slow_path(ctx == NULL)) { njs_memory_error(vm); @@ -468,118 +523,6 @@ njs_crypto_create_hmac(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static njs_int_t -njs_hmac_prototype_update(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - njs_str_t data; - njs_hmac_t *ctx; - njs_value_t *this; - - if (njs_slow_path(nargs < 2 || !njs_is_string(&args[1]))) { - njs_type_error(vm, "data must be a string"); - return NJS_ERROR; - } - - this = njs_argument(args, 0); - - if (njs_slow_path(!njs_is_object_data(this, NJS_DATA_TAG_CRYPTO_HMAC))) { - njs_type_error(vm, "\"this\" is not a hash object"); - return NJS_ERROR; - } - - njs_string_get(&args[1], &data); - - ctx = njs_object_data(this); - - if (njs_slow_path(ctx->alg == NULL)) { - njs_error(vm, "Digest already called"); - return NJS_ERROR; - } - - ctx->alg->update(&ctx->u, data.start, data.length); - - vm->retval = *this; - - return NJS_OK; -} - - -static njs_int_t -njs_hmac_prototype_digest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - u_char hash1[32], digest[32], *p; - njs_str_t enc_name, str; - njs_int_t ret; - njs_hmac_t *ctx; - njs_value_t *this; - njs_hash_alg_t *alg; - njs_crypto_enc_t *enc; - - if (njs_slow_path(nargs > 1 && !njs_is_string(&args[1]))) { - njs_type_error(vm, "encoding must be a string"); - return NJS_ERROR; - } - - this = njs_argument(args, 0); - - if (njs_slow_path(!njs_is_object_data(this, NJS_DATA_TAG_CRYPTO_HMAC))) { - njs_type_error(vm, "\"this\" is not a hash object"); - return NJS_ERROR; - } - - enc = NULL; - - if (nargs > 1) { - njs_string_get(&args[1], &enc_name); - - enc = njs_crypto_encoding(vm, &enc_name); - if (njs_slow_path(enc == NULL)) { - return NJS_ERROR; - } - } - - ctx = njs_object_data(this); - - if (njs_slow_path(ctx->alg == NULL)) { - njs_error(vm, "Digest already called"); - return NJS_ERROR; - } - - alg = ctx->alg; - - alg->final(hash1, &ctx->u); - - alg->init(&ctx->u); - alg->update(&ctx->u, ctx->opad, 64); - alg->update(&ctx->u, hash1, alg->size); - alg->final(digest, &ctx->u); - - str.start = digest; - str.length = alg->size; - - if (enc == NULL) { - p = njs_string_alloc(vm, &vm->retval, str.length, 0); - - if (njs_fast_path(p != NULL)) { - memcpy(p, str.start, str.length); - ret = NJS_OK; - - } else { - ret = NJS_ERROR; - } - - } else { - ret = enc->encode(vm, &vm->retval, &str); - } - - ctx->alg = NULL; - - return ret; -} - - static const njs_object_prop_t njs_hmac_prototype_properties[] = { { @@ -599,7 +542,8 @@ static const njs_object_prop_t njs_hmac_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("update"), - .value = njs_native_function(njs_hmac_prototype_update, 0), + .value = njs_native_function2(njs_hash_prototype_update, 0, + NJS_DATA_TAG_CRYPTO_HMAC), .writable = 1, .configurable = 1, }, @@ -607,7 +551,8 @@ static const njs_object_prop_t njs_hmac_prototype_properties[] = { .type = NJS_PROPERTY, .name = njs_string("digest"), - .value = njs_native_function(njs_hmac_prototype_digest, 0), + .value = njs_native_function2(njs_hash_prototype_digest, 0, + NJS_DATA_TAG_CRYPTO_HMAC), .writable = 1, .configurable = 1, }, @@ -716,34 +661,61 @@ const njs_object_type_init_t njs_hmac_type_init = { static njs_hash_alg_t * -njs_crypto_alg(njs_vm_t *vm, const njs_str_t *name) +njs_crypto_algorithm(njs_vm_t *vm, const njs_value_t *value) { - njs_hash_alg_t *e; + njs_str_t name; + njs_hash_alg_t *e; + + if (njs_slow_path(!njs_is_string(value))) { + njs_type_error(vm, "algorithm must be a string"); + return NULL; + } + + njs_string_get(value, &name); for (e = &njs_hash_algorithms[0]; e->name.length != 0; e++) { - if (njs_strstr_eq(name, &e->name)) { + if (njs_strstr_eq(&name, &e->name)) { return e; } } - njs_type_error(vm, "not supported algorithm: \"%V\"", name); + njs_type_error(vm, "not supported algorithm: \"%V\"", &name); return NULL; } static njs_crypto_enc_t * -njs_crypto_encoding(njs_vm_t *vm, const njs_str_t *name) +njs_crypto_encoding(njs_vm_t *vm, const njs_value_t *value) { - njs_crypto_enc_t *e; + njs_str_t name; + njs_crypto_enc_t *e; - for (e = &njs_encodings[0]; e->name.length != 0; e++) { - if (njs_strstr_eq(name, &e->name)) { + if (njs_slow_path(!njs_is_string(value))) { + if (njs_is_defined(value)) { + njs_type_error(vm, "encoding must be a string"); + return NULL; + } + + return &njs_encodings[0]; + } + + njs_string_get(value, &name); + + for (e = &njs_encodings[1]; e->name.length != 0; e++) { + if (njs_strstr_eq(&name, &e->name)) { return e; } } - njs_type_error(vm, "Unknown digest encoding: \"%V\"", name); + njs_type_error(vm, "Unknown digest encoding: \"%V\"", &name); return NULL; } + + +static njs_int_t +njs_buffer_digest(njs_vm_t *vm, njs_value_t *value, const njs_str_t *src) +{ + return njs_buffer_new(vm, value, src->start, src->length); +} diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index d6ac7694..3ba4ddc4 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -17314,49 +17314,77 @@ static njs_unit_test_t njs_test[] = "h.constructor.name"), njs_str("Hash") }, - { njs_str("var h = require('crypto').createHash('md5');" - "h.update('AB').digest('hex')"), - njs_str("b86fc6b051f63d73de262d4c34e3a0a9") }, - - { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('A').update('B').digest('hex')"), - njs_str("06d945942aa26a61be18c3e22bf19bbca8dd2b5d") }, - - { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('AB').digest('hex')"), - njs_str("06d945942aa26a61be18c3e22bf19bbca8dd2b5d") }, - - { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('AB').digest().toString('hex')"), - njs_str("06d945942aa26a61be18c3e22bf19bbca8dd2b5d") }, - - { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('AB').digest('base64')"), - njs_str("BtlFlCqiamG+GMPiK/GbvKjdK10=") }, - - { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('AB').digest('base64url')"), - njs_str("BtlFlCqiamG-GMPiK_GbvKjdK10") }, - - { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('AB').digest().toString('base64')"), - njs_str("BtlFlCqiamG+GMPiK/GbvKjdK10=") }, - - { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('abc'.repeat(100)).digest('hex')"), - njs_str("c95466320eaae6d19ee314ae4f135b12d45ced9a") }, - - { njs_str("var h = require('crypto').createHash('sha256');" - "h.update('A').update('B').digest('hex')"), - njs_str("38164fbd17603d73f696b8b4d72664d735bb6a7c88577687fd2ae33fd6964153") }, + { njs_str("var hash = require('crypto').createHash.bind(undefined, 'md5');" + "['hex', 'base64', 'base64url'].map(e => {" + " var h = hash().update('AB').digest().toString(e);" + " var h2 = hash().update(Buffer.from('XABX').subarray(1,3)).digest(e);" + " var h3 = hash().update('A').update('B').digest(e);" + " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" + " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" + " return h;" + "})"), + njs_str("b86fc6b051f63d73de262d4c34e3a0a9," + "uG/GsFH2PXPeJi1MNOOgqQ==," + "uG_GsFH2PXPeJi1MNOOgqQ") }, + + { njs_str("var hash = require('crypto').createHash.bind(undefined, 'sha1');" + "['hex', 'base64', 'base64url'].map(e => {" + " var h = hash().update('4142', 'hex').digest().toString(e);" + " var h2 = hash().update(Buffer.from('XABX').subarray(1,3)).digest(e);" + " var h3 = hash().update('A').update('B').digest(e);" + " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" + " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" + " return h;" + "})"), + njs_str("06d945942aa26a61be18c3e22bf19bbca8dd2b5d," + "BtlFlCqiamG+GMPiK/GbvKjdK10=," + "BtlFlCqiamG-GMPiK_GbvKjdK10") }, + + { njs_str("var hash = require('crypto').createHash.bind(undefined, 'sha1');" + "['hex', 'base64', 'base64url'].every(e => {" + " var h = hash().digest(e);" + " var h2 = hash().update('').digest(e);" + " if (h !== h2) {throw new Error(`digest($e):$h != update('').digest($e):$h2`)};" + " return true;" + "})"), + njs_str("true") }, - { njs_str("var h = require('crypto').createHash('sha256');" - "h.update('AB').digest('hex')"), - njs_str("38164fbd17603d73f696b8b4d72664d735bb6a7c88577687fd2ae33fd6964153") }, + { njs_str("var hash = require('crypto').createHash.bind(undefined, 'sha1');" + "[" + " ['AB']," + " ['4142', 'hex']," + " ['QUI=', 'base64']," + " ['QUI', 'base64url']" + "].every(args => {" + " return hash().update(args[0], args[1]).digest('hex') === '06d945942aa26a61be18c3e22bf19bbca8dd2b5d';" + "})"), + njs_str("true") }, - { njs_str("var h = require('crypto').createHash('sha256');" - "h.update('abc'.repeat(100)).digest('hex')"), - njs_str("d9f5aeb06abebb3be3f38adec9a2e3b94228d52193be923eb4e24c9b56ee0930") }, + { njs_str("var hash = require('crypto').createHash.bind(undefined, 'sha256');" + "['hex', 'base64', 'base64url'].map(e => {" + " var h = hash().update('AB').digest().toString(e);" + " var h2 = hash().update(Buffer.from('XABX').subarray(1,3)).digest(e);" + " var h3 = hash().update('A').update('B').digest(e);" + " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" + " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" + " return h;" + "})"), + njs_str("38164fbd17603d73f696b8b4d72664d735bb6a7c88577687fd2ae33fd6964153," + "OBZPvRdgPXP2lri01yZk1zW7anyIV3aH/SrjP9aWQVM=," + "OBZPvRdgPXP2lri01yZk1zW7anyIV3aH_SrjP9aWQVM") }, + + { njs_str("var hash = require('crypto').createHash;" + "njs.dump(['', 'abc'.repeat(100)].map(v => {" + " return ['md5', 'sha1', 'sha256'].map(h => {" + " return hash(h).update(v).digest('hex');" + " })" + "}))"), + njs_str("[['d41d8cd98f00b204e9800998ecf8427e'," + "'da39a3ee5e6b4b0d3255bfef95601890afd80709'," + "'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855']," + "['f571117acbd8153c8dc3c81b8817773a'," + "'c95466320eaae6d19ee314ae4f135b12d45ced9a'," + "'d9f5aeb06abebb3be3f38adec9a2e3b94228d52193be923eb4e24c9b56ee0930']]") }, { njs_str("var h = require('crypto').createHash()"), njs_str("TypeError: algorithm must be a string") }, @@ -17368,23 +17396,26 @@ static njs_unit_test_t njs_test[] = njs_str("TypeError: not supported algorithm: \"sha512\"") }, { njs_str("var h = require('crypto').createHash('sha1');" - "h.update()"), - njs_str("TypeError: data must be a string") }, + "h.update()"), + njs_str("TypeError: data argument \"undefined\" is not a string or Buffer-like object") }, { njs_str("var h = require('crypto').createHash('sha1');" - "h.update({})"), - njs_str("TypeError: data must be a string") }, + "h.update({})"), + njs_str("TypeError: data argument \"object\" is not a string or Buffer-like object") }, { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('A').digest('latin1')"), + "h.update('A').digest('latin1')"), njs_str("TypeError: Unknown digest encoding: \"latin1\"") }, + { njs_str("require('crypto').createHash('sha1').digest() instanceof Buffer"), + njs_str("true") }, + { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('A').digest('hex'); h.digest('hex')"), + "h.update('A').digest('hex'); h.digest('hex')"), njs_str("Error: Digest already called") }, { njs_str("var h = require('crypto').createHash('sha1');" - "h.update('A').digest('hex'); h.update('B')"), + "h.update('A').digest('hex'); h.update('B')"), njs_str("Error: Digest already called") }, { njs_str("typeof require('crypto').createHash('md5')"), @@ -17396,17 +17427,68 @@ static njs_unit_test_t njs_test[] = "[Object.prototype.toString.call(h), njs.dump(h),h]"), njs_str("[object Hmac],Hmac {},[object Hmac]") }, - { njs_str("var h = require('crypto').createHmac('md5', '');" - "h.digest('hex')"), - njs_str("74e6f7298a9c2d168935f58c001bad88") }, + { njs_str("var hmac = require('crypto').createHmac.bind(undefined, 'md5', '');" + "['hex', 'base64', 'base64url'].map(e => {" + " var h = hmac().update('AB').digest().toString(e);" + " var h2 = hmac().update(Buffer.from('XABX').subarray(1,3)).digest(e);" + " var h3 = hmac().update('A').update('B').digest(e);" + " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" + " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" + " return h;" + "})"), + njs_str("9e0e9e545ef63d41dfb653daecf8ebc7," + "ng6eVF72PUHftlPa7Pjrxw==," + "ng6eVF72PUHftlPa7Pjrxw") }, + + { njs_str("var hmac = require('crypto').createHmac.bind(undefined, 'sha1', '');" + "['hex', 'base64', 'base64url'].map(e => {" + " var h = hmac().update('AB').digest().toString(e);" + " var h2 = hmac().update(Buffer.from('XABX').subarray(1,3)).digest(e);" + " var h3 = hmac().update('A').update('B').digest(e);" + " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" + " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" + " return h;" + "})"), + njs_str("d32c0b6637cc2dfe4670f3fe48ef4434123c4810," + "0ywLZjfMLf5GcPP+SO9ENBI8SBA=," + "0ywLZjfMLf5GcPP-SO9ENBI8SBA") }, - { njs_str("var h = require('crypto').createHmac('sha1', '');" - "h.digest('hex')"), - njs_str("fbdb1d1b18aa6c08324b7d64b71fb76370690e1d") }, + { njs_str("var hash = require('crypto').createHmac.bind(undefined, 'sha1', '');" + "[" + " ['AB']," + " ['4142', 'hex']," + " ['QUI=', 'base64']," + " ['QUI', 'base64url']" + "].every(args => {" + " return hash().update(args[0], args[1]).digest('hex') === 'd32c0b6637cc2dfe4670f3fe48ef4434123c4810';" + "})"), + njs_str("true") }, - { njs_str("var h = require('crypto').createHmac('sha1', '');" - "h.digest().toString('hex')"), - njs_str("fbdb1d1b18aa6c08324b7d64b71fb76370690e1d") }, + { njs_str("var hmac = require('crypto').createHmac.bind(undefined, 'sha256', '');" + "['hex', 'base64', 'base64url'].map(e => {" + " var h = hmac().update('AB').digest().toString(e);" + " var h2 = hmac().update(Buffer.from('AB')).digest(e);" + " var h3 = hmac().update('A').update('B').digest(e);" + " if (h !== h2) {throw new Error(`digest().toString($e):$h != digest($e):$h2`)};" + " if (h !== h3) {throw new Error(`digest().toString($e):$h != update('A').update('B').digest($e):$h3`)};" + " return h;" + "})"), + njs_str("d53400095496267cf02e5dbd4b0bf9fbfb5f36f311ea7d9809af5487421743e3," + "1TQACVSWJnzwLl29Swv5+/tfNvMR6n2YCa9Uh0IXQ+M=," + "1TQACVSWJnzwLl29Swv5-_tfNvMR6n2YCa9Uh0IXQ-M") }, + + { njs_str("var hmac = require('crypto').createHmac;" + "njs.dump(['', 'abc'.repeat(100)].map(v => {" + " return ['md5', 'sha1', 'sha256'].map(h => {" + " return hmac(h, Buffer.from('secret')).update(v).digest('hex');" + " })" + "}))"), + njs_str("[['5c8db03f04cec0f43bcb060023914190'," + "'25af6174a0fcecc4d346680a72b7ce644b9a88e8'," + "'f9e66e179b6747ae54108f82f8ade8b3c25d76fd30afde6c395822c530196169']," + "['91eb74a225cdd3bbfccc34396c6e3ac5'," + "'0aac71e3a813a7acc4a809cfdedb2ecba04ffc5e'," + "'8660d2d51d6f20f61d5aadfb6c43df7fd05fc2fc4967d8aec1846f3d9ec03987']]") }, { njs_str("var h = require('crypto').createHmac('sha1', '');" "var Hmac = h.constructor; " @@ -17417,78 +17499,17 @@ static njs_unit_test_t njs_test[] = "h.constructor.name"), njs_str("Hmac") }, - { njs_str("var h = require('crypto').createHmac('md5', 'secret key');" - "h.update('AB').digest('hex')"), - njs_str("9c72728915eb26620a5caeafd0063b29") }, - - { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" - "h.update('A').update('B').digest('hex')"), - njs_str("adc60e03459c4bae7cf4eb6d9730003e9490b22f") }, - - { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" - "h.update('AB').digest('hex')"), - njs_str("adc60e03459c4bae7cf4eb6d9730003e9490b22f") }, - - { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" - "h.update('AB').digest('base64')"), - njs_str("rcYOA0WcS6589OttlzAAPpSQsi8=") }, - - { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" - "h.update('AB').digest('base64url')"), - njs_str("rcYOA0WcS6589OttlzAAPpSQsi8") }, - - { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" - "h.update('AB').digest().toString('base64')"), - njs_str("rcYOA0WcS6589OttlzAAPpSQsi8=") }, - - { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" - "h.update('abc'.repeat(100)).digest('hex')"), - njs_str("b105ad6921e4c54d3fa0a9ec3f7f0ee9bd2c659d") }, - - { njs_str("var h = require('crypto').createHmac('sha1', 'A'.repeat(40));" - "h.update('AB').digest('hex')"), - njs_str("0b84f78ca5275d76d4b7dafb5845ee2b6a79c4c2") }, - - { njs_str("var h = require('crypto').createHmac('sha1', 'A'.repeat(64));" - "h.update('AB').digest('hex')"), - njs_str("400ce530816c6b3247e2959f3982a12aaf58c0c9") }, - - { njs_str("var h = require('crypto').createHmac('sha1', 'A'.repeat(100));" - "h.update('AB').digest('hex')"), - njs_str("670e7cdebae6392797e000e79e51d3b6589d8fad") }, - - { njs_str("var h = require('crypto').createHmac('sha256', '');" - "h.digest('hex')"), - njs_str("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad") }, - - { njs_str("var h = require('crypto').createHmac('sha256', 'secret key');" - "h.update('A').update('B').digest('hex')"), - njs_str("46085184b3b45a13d838bf71a0ce03675dab30931e0f1f68fa636ea65fdb286d") }, - - { njs_str("var h = require('crypto').createHmac('sha256', 'secret key');" - "h.update('AB').digest('hex')"), - njs_str("46085184b3b45a13d838bf71a0ce03675dab30931e0f1f68fa636ea65fdb286d") }, + { njs_str("require('crypto').createHmac('sha1', '').digest() instanceof Buffer"), + njs_str("true") }, { njs_str("var h = require('crypto').createHmac('sha256', 'A'.repeat(64));" - "h.update('AB').digest('hex')"), + "h.update('AB').digest('hex')"), njs_str("ee9dce43b12eb3e865614ad9c1a8d4fad4b6eac2b64647bd24cd192888d3f367") }, { njs_str("var h = require('crypto').createHmac('sha256', 'A'.repeat(100));" - "h.update('AB').digest('hex')"), + "h.update('AB').digest('hex')"), njs_str("5647b6c429701ff512f0f18232b4507065d2376ca8899a816a0a6e721bf8ddcc") }, - { njs_str("var h = require('crypto').createHmac('md5', 'secret key');" - "h.update('abc'.repeat(100)).digest('hex')"), - njs_str("5dd706af43536f8c9c83e7ea55b1a5a2") }, - - { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" - "h.update('abc'.repeat(100)).digest('hex')"), - njs_str("b105ad6921e4c54d3fa0a9ec3f7f0ee9bd2c659d") }, - - { njs_str("var h = require('crypto').createHmac('sha256', 'secret key');" - "h.update('abc'.repeat(100)).digest('hex')"), - njs_str("f6550d398ce350ee8d94a0f44f2cf6b9bc8d316ae4625fb4434f22980a276bac") }, - { njs_str("var h = require('crypto').createHmac()"), njs_str("TypeError: algorithm must be a string") }, @@ -17499,14 +17520,14 @@ static njs_unit_test_t njs_test[] = njs_str("TypeError: not supported algorithm: \"sha512\"") }, { njs_str("var h = require('crypto').createHmac('sha1', [])"), - njs_str("TypeError: key must be a string") }, + njs_str("TypeError: key argument \"array\" is not a string or Buffer-like object") }, { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" - "h.update('A').digest('hex'); h.digest('hex')"), + "h.update('A').digest('hex'); h.digest('hex')"), njs_str("Error: Digest already called") }, { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" - "h.update('A').digest('hex'); h.update('B')"), + "h.update('A').digest('hex'); h.update('B')"), njs_str("Error: Digest already called") }, { njs_str("typeof require('crypto').createHmac('md5', 'a')"), @@ -20075,18 +20096,18 @@ static njs_unit_test_t njs_shell_test[] = { njs_str("var h = require('crypto').createHash('sha1')" ENTER "h.update([])" ENTER), - njs_str("TypeError: data must be a string\n" + njs_str("TypeError: data argument \"array\" is not a string or Buffer-like object\n" " at Hash.prototype.update (native)\n" " at main (:1)\n") }, { njs_str("require('crypto').createHmac('sha1', [])" ENTER), - njs_str("TypeError: key must be a string\n" + njs_str("TypeError: key argument \"array\" is not a string or Buffer-like object\n" " at crypto.createHmac (native)\n" " at main (:1)\n") }, { njs_str("var h = require('crypto').createHmac('sha1', 'secret')" ENTER "h.update([])" ENTER), - njs_str("TypeError: data must be a string\n" + njs_str("TypeError: data argument \"array\" is not a string or Buffer-like object\n" " at Hmac.prototype.update (native)\n" " at main (:1)\n") },