diff options
40 files changed, 1524 insertions, 56 deletions
@@ -568,14 +568,18 @@ PHP 8.0 UPGRADE NOTES . Added DateTime::createFromInterface() and DateTimeImmutable::createFromInterface(). +- Dom: + . Introduce DOMParentNode and DOMChildNode with new traversal and + manipulation APIs. + RFC: https://wiki.php.net/rfc/dom_living_standard_api + - Enchant: . enchant_dict_add() . enchant_dict_is_added() . LIBENCHANT_VERSION macro -- dom: - . Introduce DOMParentNode and DOMChildNode with new traversal and manipulation APIs - RFC: https://wiki.php.net/rfc/dom_living_standard_api +- Hash: + . HashContext objects can now be serialized. - Opcache: . If the opcache.record_warnings ini setting is enabled, opcache will record diff --git a/ext/hash/hash.c b/ext/hash/hash.c index 2d356b6133..469d91e34b 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -23,12 +23,24 @@ #include "php_hash.h" #include "ext/standard/info.h" #include "ext/standard/file.h" +#include "ext/standard/php_var.h" +#include "ext/spl/spl_exceptions.h" #include "zend_interfaces.h" #include "zend_exceptions.h" +#include "zend_smart_str.h" #include "hash_arginfo.h" +#ifdef PHP_WIN32 +# define __alignof__ __alignof +#else +# ifndef HAVE_ALIGNOF +# include <stddef.h> +# define __alignof__(type) offsetof (struct { char c; type member;}, member) +# endif +#endif + HashTable php_hash_hashtable; zend_class_entry *php_hashcontext_ce; static zend_object_handlers php_hashcontext_handlers; @@ -111,6 +123,226 @@ PHP_HASH_API int php_hash_copy(const void *ops, void *orig_context, void *dest_c } /* }}} */ + +static inline size_t align_to(size_t pos, size_t alignment) { + size_t offset = pos & (alignment - 1); + return pos + (offset ? alignment - offset : 0); +} + +static size_t parse_serialize_spec( + const char **specp, size_t *pos, size_t *sz, size_t *max_alignment) { + size_t count, alignment; + const char *spec = *specp; + /* parse size */ + if (*spec == 's' || *spec == 'S') { + *sz = 2; + alignment = __alignof__(uint16_t); /* usually 2 */ + } else if (*spec == 'l' || *spec == 'L') { + *sz = 4; + alignment = __alignof__(uint32_t); /* usually 4 */ + } else if (*spec == 'q' || *spec == 'Q') { + *sz = 8; + alignment = __alignof__(uint64_t); /* usually 8 */ + } else if (*spec == 'i' || *spec == 'I') { + *sz = sizeof(int); + alignment = __alignof__(int); /* usually 4 */ + } else { + ZEND_ASSERT(*spec == 'b' || *spec == 'B'); + *sz = 1; + alignment = 1; + } + /* process alignment */ + *pos = align_to(*pos, alignment); + *max_alignment = *max_alignment < alignment ? alignment : *max_alignment; + /* parse count */ + ++spec; + if (isdigit((unsigned char) *spec)) { + count = 0; + while (isdigit((unsigned char) *spec)) { + count = 10 * count + *spec - '0'; + ++spec; + } + } else { + count = 1; + } + *specp = spec; + return count; +} + +static uint64_t one_from_buffer(size_t sz, const unsigned char *buf) { + if (sz == 2) { + const uint16_t *x = (const uint16_t *) buf; + return *x; + } else if (sz == 4) { + const uint32_t *x = (const uint32_t *) buf; + return *x; + } else if (sz == 8) { + const uint64_t *x = (const uint64_t *) buf; + return *x; + } else { + ZEND_ASSERT(sz == 1); + return *buf; + } +} + +static void one_to_buffer(size_t sz, unsigned char *buf, uint64_t val) { + if (sz == 2) { + uint16_t *x = (uint16_t *) buf; + *x = val; + } else if (sz == 4) { + uint32_t *x = (uint32_t *) buf; + *x = val; + } else if (sz == 8) { + uint64_t *x = (uint64_t *) buf; + *x = val; + } else { + ZEND_ASSERT(sz == 1); + *buf = val; + } +} + +/* Serialize a hash context according to a `spec` string. + Spec contents: + b[COUNT] -- serialize COUNT bytes + s[COUNT] -- serialize COUNT 16-bit integers + l[COUNT] -- serialize COUNT 32-bit integers + q[COUNT] -- serialize COUNT 64-bit integers + i[COUNT] -- serialize COUNT `int`s + B[COUNT] -- skip COUNT bytes + S[COUNT], L[COUNT], etc. -- uppercase versions skip instead of read + . (must be last character) -- assert that the hash context has exactly + this size + Example: "llllllb64l16." is the spec for an MD5 context: 6 32-bit + integers, followed by 64 bytes, then 16 32-bit integers, and that's + exactly the size of the context. + + The serialization result is an array. Each integer is serialized as a + 32-bit integer, except that a run of 2 or more bytes is encoded as a + string, and each 64-bit integer is serialized as two 32-bit integers, least + significant bits first. This allows 32-bit and 64-bit architectures to + interchange serialized HashContexts. */ + +PHP_HASH_API int php_hash_serialize_spec(const php_hashcontext_object *hash, zval *zv, const char *spec) /* {{{ */ +{ + size_t pos = 0, max_alignment = 1; + unsigned char *buf = (unsigned char *) hash->context; + zval tmp; + array_init(zv); + while (*spec != '\0' && *spec != '.') { + char spec_ch = *spec; + size_t sz, count = parse_serialize_spec(&spec, &pos, &sz, &max_alignment); + if (pos + count * sz > hash->ops->context_size) { + return FAILURE; + } + if (isupper((unsigned char) spec_ch)) { + pos += count * sz; + } else if (sz == 1 && count > 1) { + ZVAL_STRINGL(&tmp, (char *) buf + pos, count); + zend_hash_next_index_insert(Z_ARRVAL_P(zv), &tmp); + pos += count; + } else { + while (count > 0) { + uint64_t val = one_from_buffer(sz, buf + pos); + pos += sz; + ZVAL_LONG(&tmp, (int32_t) val); + zend_hash_next_index_insert(Z_ARRVAL_P(zv), &tmp); + if (sz == 8) { + ZVAL_LONG(&tmp, (int32_t) (val >> 32)); + zend_hash_next_index_insert(Z_ARRVAL_P(zv), &tmp); + } + --count; + } + } + } + if (*spec == '.' && align_to(pos, max_alignment) != hash->ops->context_size) { + return FAILURE; + } + return SUCCESS; +} +/* }}} */ + +/* Unserialize a hash context serialized by `php_hash_serialize_spec` with `spec`. + Returns SUCCESS on success and a negative error code on failure. + Codes: FAILURE (-1) == generic failure + -999 == spec wrong size for context + -1000 - POS == problem at byte offset POS */ + +PHP_HASH_API int php_hash_unserialize_spec(php_hashcontext_object *hash, const zval *zv, const char *spec) /* {{{ */ +{ + size_t pos = 0, max_alignment = 1, j = 0; + unsigned char *buf = (unsigned char *) hash->context; + zval *elt; + if (Z_TYPE_P(zv) != IS_ARRAY) { + return FAILURE; + } + while (*spec != '\0' && *spec != '.') { + char spec_ch = *spec; + size_t sz, count = parse_serialize_spec(&spec, &pos, &sz, &max_alignment); + if (pos + count * sz > hash->ops->context_size) { + return -999; + } + if (isupper((unsigned char) spec_ch)) { + pos += count * sz; + } else if (sz == 1 && count > 1) { + elt = zend_hash_index_find(Z_ARRVAL_P(zv), j); + if (!elt || Z_TYPE_P(elt) != IS_STRING || Z_STRLEN_P(elt) != count) { + return -1000 - pos; + } + ++j; + memcpy(buf + pos, Z_STRVAL_P(elt), count); + pos += count; + } else { + while (count > 0) { + uint64_t val; + elt = zend_hash_index_find(Z_ARRVAL_P(zv), j); + if (!elt || Z_TYPE_P(elt) != IS_LONG) { + return -1000 - pos; + } + ++j; + val = (uint32_t) Z_LVAL_P(elt); + if (sz == 8) { + elt = zend_hash_index_find(Z_ARRVAL_P(zv), j); + if (!elt || Z_TYPE_P(elt) != IS_LONG) { + return -1000 - pos; + } + ++j; + val += ((uint64_t) Z_LVAL_P(elt)) << 32; + } + one_to_buffer(sz, buf + pos, val); + pos += sz; + --count; + } + } + } + if (*spec == '.' && align_to(pos, max_alignment) != hash->ops->context_size) { + return -999; + } + return SUCCESS; +} +/* }}} */ + +PHP_HASH_API int php_hash_serialize(const php_hashcontext_object *hash, zend_long *magic, zval *zv) /* {{{ */ +{ + if (hash->ops->serialize_spec) { + *magic = PHP_HASH_SERIALIZE_MAGIC_SPEC; + return php_hash_serialize_spec(hash, zv, hash->ops->serialize_spec); + } else { + return FAILURE; + } +} +/* }}} */ + +PHP_HASH_API int php_hash_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) /* {{{ */ +{ + if (hash->ops->serialize_spec + && magic == PHP_HASH_SERIALIZE_MAGIC_SPEC) { + return php_hash_unserialize_spec(hash, zv, hash->ops->serialize_spec); + } else { + return FAILURE; + } +} +/* }}} */ + /* Userspace */ static void php_hash_do_hash(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_bool raw_output_default) /* {{{ */ @@ -147,7 +379,7 @@ static void php_hash_do_hash(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_ } } - context = emalloc(ops->context_size); + context = php_hash_alloc_context(ops); ops->hash_init(context); if (isfilename) { @@ -271,7 +503,7 @@ static void php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAMETERS, int isfilename, } } - context = emalloc(ops->context_size); + context = php_hash_alloc_context(ops); K = emalloc(ops->block_size); digest = zend_string_alloc(ops->digest_size, 0); @@ -375,7 +607,7 @@ PHP_FUNCTION(hash_init) object_init_ex(return_value, php_hashcontext_ce); hash = php_hashcontext_from_object(Z_OBJ_P(return_value)); - context = emalloc(ops->context_size); + context = php_hash_alloc_context(ops); ops->hash_init(context); hash->ops = ops; @@ -664,7 +896,7 @@ PHP_FUNCTION(hash_hkdf) RETURN_THROWS(); } - context = emalloc(ops->context_size); + context = php_hash_alloc_context(ops); // Extract ops->hash_init(context); @@ -759,7 +991,7 @@ PHP_FUNCTION(hash_pbkdf2) RETURN_THROWS(); } - context = emalloc(ops->context_size); + context = php_hash_alloc_context(ops); ops->hash_init(context); K1 = emalloc(ops->block_size); @@ -1075,7 +1307,7 @@ PHP_FUNCTION(mhash_keygen_s2k) times++; } - context = emalloc(ops->context_size); + context = php_hash_alloc_context(ops); ops->hash_init(context); key = ecalloc(1, times * block_size); @@ -1148,7 +1380,7 @@ static zend_object *php_hashcontext_clone(zend_object *zobj) { newobj->ops = oldobj->ops; newobj->options = oldobj->options; - newobj->context = emalloc(newobj->ops->context_size); + newobj->context = php_hash_alloc_context(newobj->ops); newobj->ops->hash_init(newobj->context); if (SUCCESS != newobj->ops->hash_copy(newobj->ops, oldobj->context, newobj->context)) { @@ -1166,6 +1398,144 @@ static zend_object *php_hashcontext_clone(zend_object *zobj) { } /* }}} */ +/* Serialization format: 5-element array + Index 0: hash algorithm (string) + Index 1: options (long, 0) + Index 2: hash-determined serialization of context state (usually array) + Index 3: magic number defining layout of context state (long, usually 2) + Index 4: properties (array) + + HashContext serializations are not necessarily portable between architectures or + PHP versions. If the format of a serialized hash context changes, that should + be reflected in either a different value of `magic` or a different format of + the serialized context state. Most context states are unparsed and parsed using + a spec string, such as "llb128.", using the format defined by + `php_hash_serialize_spec`/`php_hash_unserialize_spec`. Some hash algorithms must + also check the unserialized state for validity, to ensure that using an + unserialized context is safe from memory errors. + + Currently HASH_HMAC contexts cannot be serialized, because serializing them + would require serializing the HMAC key in plaintext. */ + +/* {{{ proto array HashContext::__serialize() + Serialize the object */ +PHP_METHOD(HashContext, __serialize) +{ + zval *object = ZEND_THIS; + php_hashcontext_object *hash = php_hashcontext_from_object(Z_OBJ_P(object)); + zend_long magic = 0; + zval tmp; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + array_init(return_value); + + if (!hash->ops->hash_serialize) { + goto serialize_failure; + } else if (hash->options & PHP_HASH_HMAC) { + zend_throw_exception(NULL, "HashContext with HASH_HMAC option cannot be serialized", 0); + RETURN_THROWS(); + } + + ZVAL_STRING(&tmp, hash->ops->algo); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp); + + ZVAL_LONG(&tmp, hash->options); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp); + + if (hash->ops->hash_serialize(hash, &magic, &tmp) != SUCCESS) { + goto serialize_failure; + } + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp); + + ZVAL_LONG(&tmp, magic); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp); + + /* members */ + ZVAL_ARR(&tmp, zend_std_get_properties(&hash->std)); + Z_TRY_ADDREF(tmp); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp); + + return; + +serialize_failure: + zend_throw_exception_ex(NULL, 0, "HashContext for algorithm \"%s\" cannot be serialized", hash->ops->algo); + RETURN_THROWS(); +} +/* }}} */ + +/* {{{ proto void HashContext::__unserialize(array serialized) + * unserialize the object + */ +PHP_METHOD(HashContext, __unserialize) +{ + zval *object = ZEND_THIS; + php_hashcontext_object *hash = php_hashcontext_from_object(Z_OBJ_P(object)); + HashTable *data; + zval *algo_zv, *magic_zv, *options_zv, *hash_zv, *members_zv; + zend_long magic, options; + int unserialize_result; + const php_hash_ops *ops; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "h", &data) == FAILURE) { + RETURN_THROWS(); + } + + if (hash->context) { + zend_throw_exception(NULL, "HashContext::__unserialize called on initialized object", 0); + RETURN_THROWS(); + } + + algo_zv = zend_hash_index_find(data, 0); + options_zv = zend_hash_index_find(data, 1); + hash_zv = zend_hash_index_find(data, 2); + magic_zv = zend_hash_index_find(data, 3); + members_zv = zend_hash_index_find(data, 4); + + if (!algo_zv || Z_TYPE_P(algo_zv) != IS_STRING + || !magic_zv || Z_TYPE_P(magic_zv) != IS_LONG + || !options_zv || Z_TYPE_P(options_zv) != IS_LONG + || !hash_zv + || !members_zv || Z_TYPE_P(members_zv) != IS_ARRAY) { + zend_throw_exception(NULL, "Incomplete or ill-formed serialization data", 0); + RETURN_THROWS(); + } + + magic = Z_LVAL_P(magic_zv); + options = Z_LVAL_P(options_zv); + if (options & PHP_HASH_HMAC) { + zend_throw_exception(NULL, "HashContext with HASH_HMAC option cannot be serialized", 0); + RETURN_THROWS(); + } + + ops = php_hash_fetch_ops(Z_STR_P(algo_zv)); + if (!ops) { + zend_throw_exception(NULL, "Unknown hash algorithm", 0); + RETURN_THROWS(); + } else if (!ops->hash_unserialize) { + zend_throw_exception_ex(NULL, 0, "Hash algorithm \"%s\" cannot be unserialized", ops->algo); + RETURN_THROWS(); + } + + hash->ops = ops; + hash->context = php_hash_alloc_context(ops); + ops->hash_init(hash->context); + hash->options = options; + + unserialize_result = ops->hash_unserialize(hash, magic, hash_zv); + if (unserialize_result != SUCCESS) { + zend_throw_exception_ex(NULL, 0, "Incomplete or ill-formed serialization data (\"%s\" code %d)", ops->algo, unserialize_result); + /* free context */ + php_hashcontext_dtor(Z_OBJ_P(object)); + RETURN_THROWS(); + } + + object_properties_load(&hash->std, Z_ARRVAL_P(members_zv)); +} +/* }}} */ + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(hash) @@ -1237,8 +1607,6 @@ PHP_MINIT_FUNCTION(hash) php_hashcontext_ce = zend_register_internal_class(&ce); php_hashcontext_ce->ce_flags |= ZEND_ACC_FINAL; php_hashcontext_ce->create_object = php_hashcontext_create; - php_hashcontext_ce->serialize = zend_class_serialize_deny; - php_hashcontext_ce->unserialize = zend_class_unserialize_deny; memcpy(&php_hashcontext_handlers, &std_object_handlers, sizeof(zend_object_handlers)); diff --git a/ext/hash/hash.stub.php b/ext/hash/hash.stub.php index 32465415fc..f8788ed61e 100644 --- a/ext/hash/hash.stub.php +++ b/ext/hash/hash.stub.php @@ -53,4 +53,8 @@ function mhash(int $hash, string $data, string $key = UNKNOWN): string|false {} final class HashContext { private function __construct() {} + + public function __serialize(): array {} + + public function __unserialize(array $serialized): void {} } diff --git a/ext/hash/hash_adler32.c b/ext/hash/hash_adler32.c index 8d2d2fcb93..d45012f8e6 100644 --- a/ext/hash/hash_adler32.c +++ b/ext/hash/hash_adler32.c @@ -59,10 +59,14 @@ PHP_HASH_API int PHP_ADLER32Copy(const php_hash_ops *ops, PHP_ADLER32_CTX *orig_ } const php_hash_ops php_hash_adler32_ops = { + "adler32", (php_hash_init_func_t) PHP_ADLER32Init, (php_hash_update_func_t) PHP_ADLER32Update, (php_hash_final_func_t) PHP_ADLER32Final, (php_hash_copy_func_t) PHP_ADLER32Copy, + php_hash_serialize, + php_hash_unserialize, + PHP_ADLER32_SPEC, 4, /* what to say here? */ 4, sizeof(PHP_ADLER32_CTX), diff --git a/ext/hash/hash_arginfo.h b/ext/hash/hash_arginfo.h index c09fd12001..7ba3fca9d7 100644 --- a/ext/hash/hash_arginfo.h +++ b/ext/hash/hash_arginfo.h @@ -118,6 +118,12 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_HashContext___construct, 0, 0, 0) ZEND_END_ARG_INFO() +#define arginfo_class_HashContext___serialize arginfo_hash_algos + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_HashContext___unserialize, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, serialized, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + ZEND_FUNCTION(hash); ZEND_FUNCTION(hash_file); @@ -150,6 +156,8 @@ ZEND_FUNCTION(mhash_count); ZEND_FUNCTION(mhash); #endif ZEND_METHOD(HashContext, __construct); +ZEND_METHOD(HashContext, __serialize); +ZEND_METHOD(HashContext, __unserialize); static const zend_function_entry ext_functions[] = { @@ -189,5 +197,7 @@ static const zend_function_entry ext_functions[] = { static const zend_function_entry class_HashContext_methods[] = { ZEND_ME(HashContext, __construct, arginfo_class_HashContext___construct, ZEND_ACC_PRIVATE) + ZEND_ME(HashContext, __serialize, arginfo_class_HashContext___serialize, ZEND_ACC_PUBLIC) + ZEND_ME(HashContext, __unserialize, arginfo_class_HashContext___unserialize, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/hash/hash_crc32.c b/ext/hash/hash_crc32.c index 52c67717ff..de270522d7 100644 --- a/ext/hash/hash_crc32.c +++ b/ext/hash/hash_crc32.c @@ -78,10 +78,14 @@ PHP_HASH_API int PHP_CRC32Copy(const php_hash_ops *ops, PHP_CRC32_CTX *orig_cont } const php_hash_ops php_hash_crc32_ops = { + "crc32", (php_hash_init_func_t) PHP_CRC32Init, (php_hash_update_func_t) PHP_CRC32Update, (php_hash_final_func_t) PHP_CRC32LEFinal, (php_hash_copy_func_t) PHP_CRC32Copy, + php_hash_serialize, + php_hash_unserialize, + PHP_CRC32_SPEC, 4, /* what to say here? */ 4, sizeof(PHP_CRC32_CTX), @@ -89,10 +93,14 @@ const php_hash_ops php_hash_crc32_ops = { }; const php_hash_ops php_hash_crc32b_ops = { + "crc32b", (php_hash_init_func_t) PHP_CRC32Init, (php_hash_update_func_t) PHP_CRC32BUpdate, (php_hash_final_func_t) PHP_CRC32BEFinal, (php_hash_copy_func_t) PHP_CRC32Copy, + php_hash_serialize, + php_hash_unserialize, + PHP_CRC32_SPEC, 4, /* what to say here? */ 4, sizeof(PHP_CRC32_CTX), @@ -100,10 +108,14 @@ const php_hash_ops php_hash_crc32b_ops = { }; const php_hash_ops php_hash_crc32c_ops = { + "crc32c", (php_hash_init_func_t) PHP_CRC32Init, (php_hash_update_func_t) PHP_CRC32CUpdate, (php_hash_final_func_t) PHP_CRC32BEFinal, (php_hash_copy_func_t) PHP_CRC32Copy, + php_hash_serialize, + php_hash_unserialize, + PHP_CRC32_SPEC, 4, /* what to say here? */ 4, sizeof(PHP_CRC32_CTX), diff --git a/ext/hash/hash_fnv.c b/ext/hash/hash_fnv.c index 976c53b527..2ee81b9c86 100644 --- a/ext/hash/hash_fnv.c +++ b/ext/hash/hash_fnv.c @@ -21,10 +21,14 @@ #include "php_hash_fnv.h" const php_hash_ops php_hash_fnv132_ops = { + "fnv132", (php_hash_init_func_t) PHP_FNV132Init, (php_hash_update_func_t) PHP_FNV132Update, (php_hash_final_func_t) PHP_FNV132Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_FNV132_SPEC, 4, 4, sizeof(PHP_FNV132_CTX), @@ -32,10 +36,14 @@ const php_hash_ops php_hash_fnv132_ops = { }; const php_hash_ops php_hash_fnv1a32_ops = { + "fnv1a32", (php_hash_init_func_t) PHP_FNV132Init, (php_hash_update_func_t) PHP_FNV1a32Update, - (php_hash_final_func_t) PHP_FNV132Final, - (php_hash_copy_func_t) php_hash_copy, + (php_hash_final_func_t) PHP_FNV132Final, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_FNV132_SPEC, 4, 4, sizeof(PHP_FNV132_CTX), @@ -43,10 +51,14 @@ const php_hash_ops php_hash_fnv1a32_ops = { }; const php_hash_ops php_hash_fnv164_ops = { + "fnv164", (php_hash_init_func_t) PHP_FNV164Init, (php_hash_update_func_t) PHP_FNV164Update, (php_hash_final_func_t) PHP_FNV164Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_FNV164_SPEC, 8, 4, sizeof(PHP_FNV164_CTX), @@ -54,10 +66,14 @@ const php_hash_ops php_hash_fnv164_ops = { }; const php_hash_ops php_hash_fnv1a64_ops = { + "fnv1a64", (php_hash_init_func_t) PHP_FNV164Init, (php_hash_update_func_t) PHP_FNV1a64Update, - (php_hash_final_func_t) PHP_FNV164Final, - (php_hash_copy_func_t) php_hash_copy, + (php_hash_final_func_t) PHP_FNV164Final, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_FNV164_SPEC, 8, 4, sizeof(PHP_FNV164_CTX), diff --git a/ext/hash/hash_gost.c b/ext/hash/hash_gost.c index a9e689de16..46ea032c32 100644 --- a/ext/hash/hash_gost.c +++ b/ext/hash/hash_gost.c @@ -304,11 +304,28 @@ PHP_HASH_API void PHP_GOSTFinal(unsigned char digest[32], PHP_GOST_CTX *context) ZEND_SECURE_ZERO(context, sizeof(*context)); } +static int php_gost_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +{ + PHP_GOST_CTX *ctx = (PHP_GOST_CTX *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC + && (r = php_hash_unserialize_spec(hash, zv, PHP_GOST_SPEC)) == SUCCESS + && ctx->length < sizeof(ctx->buffer)) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} + const php_hash_ops php_hash_gost_ops = { + "gost", (php_hash_init_func_t) PHP_GOSTInit, (php_hash_update_func_t) PHP_GOSTUpdate, (php_hash_final_func_t) PHP_GOSTFinal, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_gost_unserialize, + PHP_GOST_SPEC, 32, 32, sizeof(PHP_GOST_CTX), @@ -316,10 +333,14 @@ const php_hash_ops php_hash_gost_ops = { }; const php_hash_ops php_hash_gost_crypto_ops = { + "gost-crypto", (php_hash_init_func_t) PHP_GOSTInitCrypto, (php_hash_update_func_t) PHP_GOSTUpdate, (php_hash_final_func_t) PHP_GOSTFinal, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_gost_unserialize, + PHP_GOST_SPEC, 32, 32, sizeof(PHP_GOST_CTX), diff --git a/ext/hash/hash_haval.c b/ext/hash/hash_haval.c index 62f63cbee1..34210a8992 100644 --- a/ext/hash/hash_haval.c +++ b/ext/hash/hash_haval.c @@ -247,10 +247,14 @@ static void PHP_5HAVALTransform(uint32_t state[8], const unsigned char block[128 #define PHP_HASH_HAVAL_INIT(p,b) \ const php_hash_ops php_hash_##p##haval##b##_ops = { \ + "haval" #b "," #p, \ (php_hash_init_func_t) PHP_##p##HAVAL##b##Init, \ (php_hash_update_func_t) PHP_HAVALUpdate, \ (php_hash_final_func_t) PHP_HAVAL##b##Final, \ - (php_hash_copy_func_t) php_hash_copy, \ + php_hash_copy, \ + php_hash_serialize, \ + php_hash_unserialize, \ + PHP_HAVAL_SPEC, \ ((b) / 8), 128, sizeof(PHP_HAVAL_CTX), 1 }; \ PHP_HASH_API void PHP_##p##HAVAL##b##Init(PHP_HAVAL_CTX *context) \ { int i; context->count[0] = context->count[1] = 0; \ diff --git a/ext/hash/hash_joaat.c b/ext/hash/hash_joaat.c index 10c3ca2748..5d5a2e53b9 100644 --- a/ext/hash/hash_joaat.c +++ b/ext/hash/hash_joaat.c @@ -22,10 +22,14 @@ #include "php_hash_joaat.h" const php_hash_ops php_hash_joaat_ops = { + "joaat", (php_hash_init_func_t) PHP_JOAATInit, (php_hash_update_func_t) PHP_JOAATUpdate, (php_hash_final_func_t) PHP_JOAATFinal, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_JOAAT_SPEC, 4, 4, sizeof(PHP_JOAAT_CTX), diff --git a/ext/hash/hash_md.c b/ext/hash/hash_md.c index e5cbb49b01..94fafbbf79 100644 --- a/ext/hash/hash_md.c +++ b/ext/hash/hash_md.c @@ -18,10 +18,14 @@ #include "php_hash_md.h" const php_hash_ops php_hash_md5_ops = { + "md5", (php_hash_init_func_t) PHP_MD5Init, (php_hash_update_func_t) PHP_MD5Update, (php_hash_final_func_t) PHP_MD5Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_MD5_SPEC, 16, 64, sizeof(PHP_MD5_CTX), @@ -29,21 +33,31 @@ const php_hash_ops php_hash_md5_ops = { }; const php_hash_ops php_hash_md4_ops = { + "md4", (php_hash_init_func_t) PHP_MD4Init, (php_hash_update_func_t) PHP_MD4Update, (php_hash_final_func_t) PHP_MD4Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_MD4_SPEC, 16, 64, sizeof(PHP_MD4_CTX), 1 }; +static int php_md2_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv); + const php_hash_ops php_hash_md2_ops = { + "md2", (php_hash_init_func_t) PHP_MD2Init, (php_hash_update_func_t) PHP_MD2Update, (php_hash_final_func_t) PHP_MD2Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_md2_unserialize, + PHP_MD2_SPEC, 16, 16, sizeof(PHP_MD2_CTX), @@ -340,3 +354,16 @@ PHP_HASH_API void PHP_MD2Final(unsigned char output[16], PHP_MD2_CTX *context) memcpy(output, context->state, 16); } + +static int php_md2_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +{ + PHP_MD2_CTX *ctx = (PHP_MD2_CTX *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC + && (r = php_hash_unserialize_spec(hash, zv, PHP_MD2_SPEC)) == SUCCESS + && (unsigned char) ctx->in_buffer < sizeof(ctx->buffer)) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} diff --git a/ext/hash/hash_ripemd.c b/ext/hash/hash_ripemd.c index 84a29f6486..db1d1dc02b 100644 --- a/ext/hash/hash_ripemd.c +++ b/ext/hash/hash_ripemd.c @@ -22,10 +22,14 @@ #include "php_hash_ripemd.h" const php_hash_ops php_hash_ripemd128_ops = { + "ripemd128", (php_hash_init_func_t) PHP_RIPEMD128Init, (php_hash_update_func_t) PHP_RIPEMD128Update, (php_hash_final_func_t) PHP_RIPEMD128Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_RIPEMD128_SPEC, 16, 64, sizeof(PHP_RIPEMD128_CTX), @@ -33,10 +37,14 @@ const php_hash_ops php_hash_ripemd128_ops = { }; const php_hash_ops php_hash_ripemd160_ops = { + "ripemd160", (php_hash_init_func_t) PHP_RIPEMD160Init, (php_hash_update_func_t) PHP_RIPEMD160Update, (php_hash_final_func_t) PHP_RIPEMD160Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_RIPEMD160_SPEC, 20, 64, sizeof(PHP_RIPEMD160_CTX), @@ -44,10 +52,14 @@ const php_hash_ops php_hash_ripemd160_ops = { }; const php_hash_ops php_hash_ripemd256_ops = { + "ripemd256", (php_hash_init_func_t) PHP_RIPEMD256Init, (php_hash_update_func_t) PHP_RIPEMD256Update, (php_hash_final_func_t) PHP_RIPEMD256Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_RIPEMD256_SPEC, 32, 64, sizeof(PHP_RIPEMD256_CTX), @@ -55,10 +67,14 @@ const php_hash_ops php_hash_ripemd256_ops = { }; const php_hash_ops php_hash_ripemd320_ops = { + "ripemd320", (php_hash_init_func_t) PHP_RIPEMD320Init, (php_hash_update_func_t) PHP_RIPEMD320Update, (php_hash_final_func_t) PHP_RIPEMD320Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_RIPEMD320_SPEC, 40, 64, sizeof(PHP_RIPEMD320_CTX), diff --git a/ext/hash/hash_sha.c b/ext/hash/hash_sha.c index 30ab0d22ad..4ea5b768d7 100644 --- a/ext/hash/hash_sha.c +++ b/ext/hash/hash_sha.c @@ -63,10 +63,14 @@ static void SHADecode32(uint32_t *output, const unsigned char *input, unsigned i /* }}} */ const php_hash_ops php_hash_sha1_ops = { + "sha1", (php_hash_init_func_t) PHP_SHA1Init, (php_hash_update_func_t) PHP_SHA1Update, (php_hash_final_func_t) PHP_SHA1Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA1_SPEC, 20, 64, sizeof(PHP_SHA1_CTX), @@ -76,10 +80,14 @@ const php_hash_ops php_hash_sha1_ops = { /* sha224/sha256 */ const php_hash_ops php_hash_sha256_ops = { + "sha256", (php_hash_init_func_t) PHP_SHA256Init, (php_hash_update_func_t) PHP_SHA256Update, (php_hash_final_func_t) PHP_SHA256Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA256_SPEC, 32, 64, sizeof(PHP_SHA256_CTX), @@ -87,10 +95,14 @@ const php_hash_ops php_hash_sha256_ops = { }; const php_hash_ops php_hash_sha224_ops = { + "sha224", (php_hash_init_func_t) PHP_SHA224Init, (php_hash_update_func_t) PHP_SHA224Update, (php_hash_final_func_t) PHP_SHA224Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA224_SPEC, 28, 64, sizeof(PHP_SHA224_CTX), @@ -578,10 +590,14 @@ PHP_HASH_API void PHP_SHA384Final(unsigned char digest[48], PHP_SHA384_CTX * con /* }}} */ const php_hash_ops php_hash_sha384_ops = { + "sha384", (php_hash_init_func_t) PHP_SHA384Init, (php_hash_update_func_t) PHP_SHA384Update, (php_hash_final_func_t) PHP_SHA384Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA384_SPEC, 48, 128, sizeof(PHP_SHA384_CTX), @@ -751,10 +767,14 @@ PHP_HASH_API void PHP_SHA512_224Final(unsigned char digest[28], PHP_SHA512_CTX * /* }}} */ const php_hash_ops php_hash_sha512_ops = { + "sha512", (php_hash_init_func_t) PHP_SHA512Init, (php_hash_update_func_t) PHP_SHA512Update, (php_hash_final_func_t) PHP_SHA512Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA512_SPEC, 64, 128, sizeof(PHP_SHA512_CTX), @@ -762,10 +782,14 @@ const php_hash_ops php_hash_sha512_ops = { }; const php_hash_ops php_hash_sha512_256_ops = { + "sha512/256", (php_hash_init_func_t) PHP_SHA512_256Init, (php_hash_update_func_t) PHP_SHA512_256Update, (php_hash_final_func_t) PHP_SHA512_256Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA512_SPEC, 32, 128, sizeof(PHP_SHA512_CTX), @@ -773,10 +797,14 @@ const php_hash_ops php_hash_sha512_256_ops = { }; const php_hash_ops php_hash_sha512_224_ops = { + "sha512/224", (php_hash_init_func_t) PHP_SHA512_224Init, (php_hash_update_func_t) PHP_SHA512_224Update, (php_hash_final_func_t) PHP_SHA512_224Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA512_SPEC, 28, 128, sizeof(PHP_SHA512_CTX), diff --git a/ext/hash/hash_sha3.c b/ext/hash/hash_sha3.c index 32621514a8..52bd495f9d 100644 --- a/ext/hash/hash_sha3.c +++ b/ext/hash/hash_sha3.c @@ -201,6 +201,22 @@ static void PHP_SHA3_Final(unsigned char* digest, ZEND_SECURE_ZERO(ctx, sizeof(PHP_SHA3_CTX)); } +static int php_sha3_unserialize(php_hashcontext_object *hash, + zend_long magic, + const zval *zv, + size_t block_size) +{ + PHP_SHA3_CTX *ctx = (PHP_SHA3_CTX *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC + && (r = php_hash_unserialize_spec(hash, zv, PHP_SHA3_SPEC)) == SUCCESS + && ctx->pos < block_size) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} + // ========================================================================== #define DECLARE_SHA3_OPS(bits) \ @@ -219,11 +235,20 @@ void PHP_SHA3##bits##Final(unsigned char* digest, \ (1600 - (2 * bits)) >> 3, \ bits >> 3); \ } \ +static int php_sha3##bits##_unserialize(php_hashcontext_object *hash, \ + zend_long magic, \ + const zval *zv) { \ + return php_sha3_unserialize(hash, magic, zv, (1600 - (2 * bits)) >> 3); \ +} \ const php_hash_ops php_hash_sha3_##bits##_ops = { \ + "sha3-" #bits, \ (php_hash_init_func_t) PHP_SHA3##bits##Init, \ (php_hash_update_func_t) PHP_SHA3##bits##Update, \ (php_hash_final_func_t) PHP_SHA3##bits##Final, \ php_hash_copy, \ + php_hash_serialize, \ + php_sha3##bits##_unserialize, \ + PHP_SHA3_SPEC, \ bits >> 3, \ (1600 - (2 * bits)) >> 3, \ sizeof(PHP_SHA3_##bits##_CTX), \ @@ -237,6 +262,55 @@ const php_hash_ops php_hash_sha3_##bits##_ops = { \ #define SUCCESS SHA3_SUCCESS /* Avoid conflict between KeccacHash.h and zend_types.h */ #include "KeccakHash.h" +/* KECCAK SERIALIZATION + + Keccak_HashInstance consists of: + KeccakWidth1600_SpongeInstance { + unsigned char state[200]; + unsigned int rate; -- fixed for digest size + unsigned int byteIOIndex; -- in range [0, rate/8) + int squeezing; -- 0 normally, 1 only during finalize + } sponge; + unsigned int fixedOutputLength; -- fixed for digest size + unsigned char delimitedSuffix; -- fixed for digest size + + NB If the external sha3/ library is updated, the serialization code + may need to be updated. + + The simpler SHA3 code's serialization states are not interchangeable with + Keccak. Furthermore, the Keccak sponge state is sensitive to architecture + -- 32-bit and 64-bit implementations produce different states. It does not + appear that the state is sensitive to endianness. */ + +#if Keccak_HashInstance_ImplType == 64 +/* corresponds to sha3/generic64lc */ +# define PHP_HASH_SERIALIZE_MAGIC_KECCAK 100 +#elif Keccak_HashInstance_ImplType == 32 +/* corresponds to sha3/generic32lc */ +# define PHP_HASH_SERIALIZE_MAGIC_KECCAK 101 +#else +# error "Unknown Keccak_HashInstance_ImplType" +#endif +#define PHP_KECCAK_SPEC "b200IiIIB" + +static int php_keccak_serialize(const php_hashcontext_object *hash, zend_long *magic, zval *zv) +{ + *magic = PHP_HASH_SERIALIZE_MAGIC_KECCAK; + return php_hash_serialize_spec(hash, zv, PHP_KECCAK_SPEC); +} + +static int php_keccak_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +{ + Keccak_HashInstance *ctx = (Keccak_HashInstance *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_KECCAK + && (r = php_hash_unserialize_spec(hash, zv, PHP_KECCAK_SPEC)) == SUCCESS + && ctx->sponge.byteIOIndex < ctx->sponge.rate / 8) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} // ========================================================================== @@ -255,10 +329,14 @@ void PHP_SHA3##bits##Final(unsigned char* digest, \ Keccak_HashFinal((Keccak_HashInstance *)ctx, digest); \ } \ const php_hash_ops php_hash_sha3_##bits##_ops = { \ + "sha3-" #bits, \ (php_hash_init_func_t) PHP_SHA3##bits##Init, \ (php_hash_update_func_t) PHP_SHA3##bits##Update, \ (php_hash_final_func_t) PHP_SHA3##bits##Final, \ php_hash_copy, \ + php_keccak_serialize, \ + php_keccak_unserialize, \ + PHP_KECCAK_SPEC, \ bits >> 3, \ (1600 - (2 * bits)) >> 3, \ sizeof(PHP_SHA3_CTX), \ diff --git a/ext/hash/hash_snefru.c b/ext/hash/hash_snefru.c index fae767f2fe..292bfef2cb 100644 --- a/ext/hash/hash_snefru.c +++ b/ext/hash/hash_snefru.c @@ -189,11 +189,28 @@ PHP_HASH_API void PHP_SNEFRUFinal(unsigned char digest[32], PHP_SNEFRU_CTX *cont ZEND_SECURE_ZERO(context, sizeof(*context)); } +static int php_snefru_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +{ + PHP_SNEFRU_CTX *ctx = (PHP_SNEFRU_CTX *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC + && (r = php_hash_unserialize_spec(hash, zv, PHP_SNEFRU_SPEC)) == SUCCESS + && ctx->length < sizeof(ctx->buffer)) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} + const php_hash_ops php_hash_snefru_ops = { + "snefru", (php_hash_init_func_t) PHP_SNEFRUInit, (php_hash_update_func_t) PHP_SNEFRUUpdate, (php_hash_final_func_t) PHP_SNEFRUFinal, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_snefru_unserialize, + PHP_SNEFRU_SPEC, 32, 32, sizeof(PHP_SNEFRU_CTX), diff --git a/ext/hash/hash_tiger.c b/ext/hash/hash_tiger.c index 399e95af0e..8e0f365dc4 100644 --- a/ext/hash/hash_tiger.c +++ b/ext/hash/hash_tiger.c @@ -239,12 +239,29 @@ PHP_HASH_API void PHP_TIGER192Final(unsigned char digest[24], PHP_TIGER_CTX *con ZEND_SECURE_ZERO(context, sizeof(*context)); } +static int php_tiger_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +{ + PHP_TIGER_CTX *ctx = (PHP_TIGER_CTX *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC + && (r = php_hash_unserialize_spec(hash, zv, PHP_TIGER_SPEC)) == SUCCESS + && ctx->length < sizeof(ctx->buffer)) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} + #define PHP_HASH_TIGER_OPS(p, b) \ const php_hash_ops php_hash_##p##tiger##b##_ops = { \ + "tiger" #b "," #p, \ (php_hash_init_func_t) PHP_##p##TIGERInit, \ (php_hash_update_func_t) PHP_TIGERUpdate, \ (php_hash_final_func_t) PHP_TIGER##b##Final, \ - (php_hash_copy_func_t) php_hash_copy, \ + php_hash_copy, \ + php_hash_serialize, \ + php_tiger_unserialize, \ + PHP_TIGER_SPEC, \ b/8, \ 64, \ sizeof(PHP_TIGER_CTX), \ diff --git a/ext/hash/hash_whirlpool.c b/ext/hash/hash_whirlpool.c index 5be7f80eea..8d5cbb7737 100644 --- a/ext/hash/hash_whirlpool.c +++ b/ext/hash/hash_whirlpool.c @@ -429,11 +429,31 @@ PHP_HASH_API void PHP_WHIRLPOOLFinal(unsigned char digest[64], PHP_WHIRLPOOL_CTX ZEND_SECURE_ZERO(context, sizeof(*context)); } +static int php_whirlpool_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +{ + PHP_WHIRLPOOL_CTX *ctx = (PHP_WHIRLPOOL_CTX *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC + && (r = php_hash_unserialize_spec(hash, zv, PHP_WHIRLPOOL_SPEC)) == SUCCESS + && ctx->buffer.pos >= 0 + && ctx->buffer.pos < (int) sizeof(ctx->buffer.data) + && ctx->buffer.bits >= ctx->buffer.pos * 8 + && ctx->buffer.bits < ctx->buffer.pos * 8 + 8) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} + const php_hash_ops php_hash_whirlpool_ops = { + "whirlpool", (php_hash_init_func_t) PHP_WHIRLPOOLInit, (php_hash_update_func_t) PHP_WHIRLPOOLUpdate, (php_hash_final_func_t) PHP_WHIRLPOOLFinal, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_whirlpool_unserialize, + PHP_WHIRLPOOL_SPEC, 64, 64, sizeof(PHP_WHIRLPOOL_CTX), diff --git a/ext/hash/php_hash.h b/ext/hash/php_hash.h index 79bbc066d6..33cc6a473a 100644 --- a/ext/hash/php_hash.h +++ b/ext/hash/php_hash.h @@ -25,18 +25,28 @@ #define PHP_HASH_HMAC 0x0001 +#define PHP_HASH_SERIALIZE_MAGIC_SPEC 2 + #define L64 INT64_C +typedef struct _php_hashcontext_object php_hashcontext_object; + typedef void (*php_hash_init_func_t)(void *context); typedef void (*php_hash_update_func_t)(void *context, const unsigned char *buf, size_t count); typedef void (*php_hash_final_func_t)(unsigned char *digest, void *context); typedef int (*php_hash_copy_func_t)(const void *ops, void *orig_context, void *dest_context); +typedef int (*php_hash_serialize_func_t)(const php_hashcontext_object *hash, zend_long *magic, zval *zv); +typedef int (*php_hash_unserialize_func_t)(php_hashcontext_object *hash, zend_long magic, const zval *zv); typedef struct _php_hash_ops { + const char *algo; php_hash_init_func_t hash_init; php_hash_update_func_t hash_update; php_hash_final_func_t hash_final; php_hash_copy_func_t hash_copy; + php_hash_serialize_func_t hash_serialize; + php_hash_unserialize_func_t hash_unserialize; + const char *serialize_spec; size_t digest_size; size_t block_size; @@ -44,7 +54,7 @@ typedef struct _php_hash_ops { unsigned is_crypto: 1; } php_hash_ops; -typedef struct _php_hashcontext_object { +struct _php_hashcontext_object { const php_hash_ops *ops; void *context; @@ -52,7 +62,7 @@ typedef struct _php_hashcontext_object { unsigned char *key; zend_object std; -} php_hashcontext_object; +}; static inline php_hashcontext_object *php_hashcontext_from_object(zend_object *obj) { return ((php_hashcontext_object*)(obj + 1)) - 1; @@ -131,6 +141,15 @@ extern PHP_HASH_API zend_class_entry *php_hashcontext_ce; PHP_HASH_API const php_hash_ops *php_hash_fetch_ops(zend_string *algo); PHP_HASH_API void php_hash_register_algo(const char *algo, const php_hash_ops *ops); PHP_HASH_API int php_hash_copy(const void *ops, void *orig_context, void *dest_context); +PHP_HASH_API int php_hash_serialize(const php_hashcontext_object *context, zend_long *magic, zval *zv); +PHP_HASH_API int php_hash_unserialize(php_hashcontext_object *context, zend_long magic, const zval *zv); +PHP_HASH_API int php_hash_serialize_spec(const php_hashcontext_object *context, zval *zv, const char *spec); +PHP_HASH_API int php_hash_unserialize_spec(php_hashcontext_object *hash, const zval *zv, const char *spec); + +static inline void *php_hash_alloc_context(const php_hash_ops *ops) { + /* Zero out context memory so serialization doesn't expose internals */ + return ecalloc(1, ops->context_size); +} static inline void php_hash_bin2hex(char *out, const unsigned char *in, size_t in_len) { diff --git a/ext/hash/php_hash_adler32.h b/ext/hash/php_hash_adler32.h index 184091c971..049f16b28e 100644 --- a/ext/hash/php_hash_adler32.h +++ b/ext/hash/php_hash_adler32.h @@ -22,6 +22,7 @@ typedef struct { uint32_t state; } PHP_ADLER32_CTX; +#define PHP_ADLER32_SPEC "l." PHP_HASH_API void PHP_ADLER32Init(PHP_ADLER32_CTX *context); PHP_HASH_API void PHP_ADLER32Update(PHP_ADLER32_CTX *context, const unsigned char *input, size_t len); diff --git a/ext/hash/php_hash_crc32.h b/ext/hash/php_hash_crc32.h index 346011e417..4c1b0fedc9 100644 --- a/ext/hash/php_hash_crc32.h +++ b/ext/hash/php_hash_crc32.h @@ -22,6 +22,7 @@ typedef struct { uint32_t state; } PHP_CRC32_CTX; +#define PHP_CRC32_SPEC "l." PHP_HASH_API void PHP_CRC32Init(PHP_CRC32_CTX *context); PHP_HASH_API void PHP_CRC32Update(PHP_CRC32_CTX *context, const unsigned char *input, size_t len); diff --git a/ext/hash/php_hash_fnv.h b/ext/hash/php_hash_fnv.h index 1cb8c78d29..6728b2e902 100644 --- a/ext/hash/php_hash_fnv.h +++ b/ext/hash/php_hash_fnv.h @@ -44,10 +44,12 @@ enum php_fnv_type { typedef struct { uint32_t state; } PHP_FNV132_CTX; +#define PHP_FNV132_SPEC "l." typedef struct { uint64_t state; } PHP_FNV164_CTX; +#define PHP_FNV164_SPEC "q." PHP_HASH_API void PHP_FNV132Init(PHP_FNV132_CTX *context); diff --git a/ext/hash/php_hash_gost.h b/ext/hash/php_hash_gost.h index 987eb655cb..eb9441faa6 100644 --- a/ext/hash/php_hash_gost.h +++ b/ext/hash/php_hash_gost.h @@ -27,6 +27,7 @@ typedef struct { unsigned char buffer[32]; const uint32_t (*tables)[4][256]; } PHP_GOST_CTX; +#define PHP_GOST_SPEC "l16l2bb32" PHP_HASH_API void PHP_GOSTInit(PHP_GOST_CTX *); PHP_HASH_API void PHP_GOSTUpdate(PHP_GOST_CTX *, const unsigned char *, size_t); diff --git a/ext/hash/php_hash_haval.h b/ext/hash/php_hash_haval.h index 8eaaf2d2b7..43802b4183 100644 --- a/ext/hash/php_hash_haval.h +++ b/ext/hash/php_hash_haval.h @@ -28,6 +28,7 @@ typedef struct { short output; void (*Transform)(uint32_t state[8], const unsigned char block[128]); } PHP_HAVAL_CTX; +#define PHP_HAVAL_SPEC "l8l2b128" #define PHP_HASH_HAVAL_INIT_DECL(p,b) PHP_HASH_API void PHP_##p##HAVAL##b##Init(PHP_HAVAL_CTX *); \ PHP_HASH_API void PHP_HAVAL##b##Final(unsigned char*, PHP_HAVAL_CTX *); diff --git a/ext/hash/php_hash_joaat.h b/ext/hash/php_hash_joaat.h index ede108f1bb..b0df8a67b3 100644 --- a/ext/hash/php_hash_joaat.h +++ b/ext/hash/php_hash_joaat.h @@ -20,6 +20,7 @@ typedef struct { uint32_t state; } PHP_JOAAT_CTX; +#define PHP_JOAAT_SPEC "l." PHP_HASH_API void PHP_JOAATInit(PHP_JOAAT_CTX *context); PHP_HASH_API void PHP_JOAATUpdate(PHP_JOAAT_CTX *context, const unsigned char *input, size_t inputLen); diff --git a/ext/hash/php_hash_md.h b/ext/hash/php_hash_md.h index aed999261e..2a677fe54d 100644 --- a/ext/hash/php_hash_md.h +++ b/ext/hash/php_hash_md.h @@ -26,6 +26,7 @@ typedef struct { uint32_t count[2]; unsigned char buffer[64]; } PHP_MD4_CTX; +#define PHP_MD4_SPEC "l4l2b64." PHP_HASH_API void PHP_MD4Init(PHP_MD4_CTX *); PHP_HASH_API void PHP_MD4Update(PHP_MD4_CTX *context, const unsigned char *, size_t); @@ -36,8 +37,9 @@ typedef struct { unsigned char state[48]; unsigned char checksum[16]; unsigned char buffer[16]; - char in_buffer; + unsigned char in_buffer; } PHP_MD2_CTX; +#define PHP_MD2_SPEC "b48b16b16b." PHP_HASH_API void PHP_MD2Init(PHP_MD2_CTX *context); PHP_HASH_API void PHP_MD2Update(PHP_MD2_CTX *context, const unsigned char *, size_t); diff --git a/ext/hash/php_hash_ripemd.h b/ext/hash/php_hash_ripemd.h index 131dd0ad8f..dd9913b85b 100644 --- a/ext/hash/php_hash_ripemd.h +++ b/ext/hash/php_hash_ripemd.h @@ -24,24 +24,28 @@ typedef struct { uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_RIPEMD128_CTX; +#define PHP_RIPEMD128_SPEC "l4l2b64." typedef struct { uint32_t state[5]; /* state (ABCD) */ uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_RIPEMD160_CTX; +#define PHP_RIPEMD160_SPEC "l5l2b64." typedef struct { uint32_t state[8]; /* state (ABCD) */ uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_RIPEMD256_CTX; +#define PHP_RIPEMD256_SPEC "l8l2b64." typedef struct { uint32_t state[10]; /* state (ABCD) */ uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_RIPEMD320_CTX; +#define PHP_RIPEMD320_SPEC "l10l2b64." PHP_HASH_API void PHP_RIPEMD128Init(PHP_RIPEMD128_CTX *); PHP_HASH_API void PHP_RIPEMD128Update(PHP_RIPEMD128_CTX *, const unsigned char *, size_t); diff --git a/ext/hash/php_hash_sha.h b/ext/hash/php_hash_sha.h index 95471e7398..16da927363 100644 --- a/ext/hash/php_hash_sha.h +++ b/ext/hash/php_hash_sha.h @@ -27,6 +27,7 @@ typedef struct { uint32_t count[2]; /* number of bits, modulo 2^64 */ unsigned char buffer[64]; /* input buffer */ } PHP_SHA224_CTX; +#define PHP_SHA224_SPEC "l8l2b64." PHP_HASH_API void PHP_SHA224Init(PHP_SHA224_CTX *); PHP_HASH_API void PHP_SHA224Update(PHP_SHA224_CTX *, const unsigned char *, size_t); @@ -38,6 +39,7 @@ typedef struct { uint32_t count[2]; /* number of bits, modulo 2^64 */ unsigned char buffer[64]; /* input buffer */ } PHP_SHA256_CTX; +#define PHP_SHA256_SPEC "l8l2b64." PHP_HASH_API void PHP_SHA256Init(PHP_SHA256_CTX *); PHP_HASH_API void PHP_SHA256Update(PHP_SHA256_CTX *, const unsigned char *, size_t); @@ -49,6 +51,7 @@ typedef struct { uint64_t count[2]; /* number of bits, modulo 2^128 */ unsigned char buffer[128]; /* input buffer */ } PHP_SHA384_CTX; +#define PHP_SHA384_SPEC "q8q2b128." PHP_HASH_API void PHP_SHA384Init(PHP_SHA384_CTX *); PHP_HASH_API void PHP_SHA384Update(PHP_SHA384_CTX *, const unsigned char *, size_t); @@ -60,6 +63,7 @@ typedef struct { uint64_t count[2]; /* number of bits, modulo 2^128 */ unsigned char buffer[128]; /* input buffer */ } PHP_SHA512_CTX; +#define PHP_SHA512_SPEC "q8q2b128." PHP_HASH_API void PHP_SHA512Init(PHP_SHA512_CTX *); PHP_HASH_API void PHP_SHA512Update(PHP_SHA512_CTX *, const unsigned char *, size_t); diff --git a/ext/hash/php_hash_sha3.h b/ext/hash/php_hash_sha3.h index bb392c0ab0..f75191f339 100644 --- a/ext/hash/php_hash_sha3.h +++ b/ext/hash/php_hash_sha3.h @@ -27,6 +27,9 @@ typedef struct { unsigned char state[224]; // this must fit a Keccak_HashInstance #endif } PHP_SHA3_CTX; +#ifdef HAVE_SLOW_HASH3 +#define PHP_SHA3_SPEC "b200l." +#endif typedef PHP_SHA3_CTX PHP_SHA3_224_CTX; typedef PHP_SHA3_CTX PHP_SHA3_256_CTX; diff --git a/ext/hash/php_hash_snefru.h b/ext/hash/php_hash_snefru.h index 25ba1183e3..0f339e9309 100644 --- a/ext/hash/php_hash_snefru.h +++ b/ext/hash/php_hash_snefru.h @@ -30,6 +30,7 @@ typedef struct { unsigned char length; unsigned char buffer[32]; } PHP_SNEFRU_CTX; +#define PHP_SNEFRU_SPEC "l16l2bb32" PHP_HASH_API void PHP_SNEFRUInit(PHP_SNEFRU_CTX *); PHP_HASH_API void PHP_SNEFRUUpdate(PHP_SNEFRU_CTX *, const unsigned char *, size_t); diff --git a/ext/hash/php_hash_tiger.h b/ext/hash/php_hash_tiger.h index 4476639040..d30276ddea 100644 --- a/ext/hash/php_hash_tiger.h +++ b/ext/hash/php_hash_tiger.h @@ -22,9 +22,10 @@ typedef struct { uint64_t state[3]; uint64_t passed; unsigned char buffer[64]; + uint32_t length; unsigned int passes:1; - size_t length; } PHP_TIGER_CTX; +#define PHP_TIGER_SPEC "q3qb64l" PHP_HASH_API void PHP_3TIGERInit(PHP_TIGER_CTX *context); PHP_HASH_API void PHP_4TIGERInit(PHP_TIGER_CTX *context); diff --git a/ext/hash/php_hash_whirlpool.h b/ext/hash/php_hash_whirlpool.h index f96da414a5..fbd5948a48 100644 --- a/ext/hash/php_hash_whirlpool.h +++ b/ext/hash/php_hash_whirlpool.h @@ -27,6 +27,7 @@ typedef struct { unsigned char data[64]; } buffer; } PHP_WHIRLPOOL_CTX; +#define PHP_WHIRLPOOL_SPEC "q8b32iib64." PHP_HASH_API void PHP_WHIRLPOOLInit(PHP_WHIRLPOOL_CTX *); PHP_HASH_API void PHP_WHIRLPOOLUpdate(PHP_WHIRLPOOL_CTX *, const unsigned char *, size_t); diff --git a/ext/hash/sha3/generic32lc/KeccakHash.h b/ext/hash/sha3/generic32lc/KeccakHash.h index ec35d3dab2..d53ac1c587 100644 --- a/ext/hash/sha3/generic32lc/KeccakHash.h +++ b/ext/hash/sha3/generic32lc/KeccakHash.h @@ -108,6 +108,8 @@ HashReturn Keccak_HashFinal(Keccak_HashInstance *hashInstance, BitSequence *hash */ HashReturn Keccak_HashSqueeze(Keccak_HashInstance *hashInstance, BitSequence *data, DataLength databitlen); +#define Keccak_HashInstance_ImplType 32 + #endif #endif diff --git a/ext/hash/sha3/generic64lc/KeccakHash.h b/ext/hash/sha3/generic64lc/KeccakHash.h index ec35d3dab2..6afe6c8c9a 100644 --- a/ext/hash/sha3/generic64lc/KeccakHash.h +++ b/ext/hash/sha3/generic64lc/KeccakHash.h @@ -108,6 +108,8 @@ HashReturn Keccak_HashFinal(Keccak_HashInstance *hashInstance, BitSequence *hash */ HashReturn Keccak_HashSqueeze(Keccak_HashInstance *hashInstance, BitSequence *data, DataLength databitlen); +#define Keccak_HashInstance_ImplType 64 + #endif #endif diff --git a/ext/hash/tests/hash_serialize_001.phpt b/ext/hash/tests/hash_serialize_001.phpt new file mode 100644 index 0000000000..d515d2c5c5 --- /dev/null +++ b/ext/hash/tests/hash_serialize_001.phpt @@ -0,0 +1,361 @@ +--TEST-- +Hash: serialize()/unserialize() +--FILE-- +<?php + +$algos = hash_algos(); + +foreach ($algos as $algo) { + var_dump($algo); + $ctx0 = hash_init($algo); + $serial = serialize($ctx0); + assert(is_string($serial)); + + $ctx1 = unserialize($serial); + hash_update($ctx1, "I can't remember anything"); + $serial = serialize($ctx1); + assert(is_string($serial)); + var_dump(hash_final($ctx1)); + + $ctx2 = unserialize($serial); + var_dump(hash_final($ctx2)); +} + +// serialize/unserialize produces same results as all-on-one +foreach ($algos as $algo) { + var_dump($algo); + $orig = hash_init($algo); + hash_update($orig, "I can't remember anything"); + $serial = serialize($orig); + + $fresh = hash_init($algo); + hash_update($fresh, "I can't remember anythingCan’t tell if this is true or dream"); + var_dump(hash_final($fresh)); + + $copy = unserialize($serial); + hash_update($copy, "Can’t tell if this is true or dream"); + var_dump(hash_final($copy)); +} + +echo "Done\n"; +?> +--EXPECT-- +string(3) "md2" +string(32) "d5ac4ffd08f6a57b9bd402b8068392ff" +string(32) "d5ac4ffd08f6a57b9bd402b8068392ff" +string(3) "md4" +string(32) "302c45586b53a984bd3a1237cb81c15f" +string(32) "302c45586b53a984bd3a1237cb81c15f" +string(3) "md5" +string(32) "e35759f6ea35db254e415b5332269435" +string(32) "e35759f6ea35db254e415b5332269435" +string(4) "sha1" +string(40) "29f62a228f726cd728efa7a0ac6a2aba318baf15" +string(40) "29f62a228f726cd728efa7a0ac6a2aba318baf15" +string(6) "sha224" +string(56) "51fd0aa76a00b4a86103895cad5c7c2651ec7da9f4fc1e50c43ede29" +string(56) "51fd0aa76a00b4a86103895cad5c7c2651ec7da9f4fc1e50c43ede29" +string(6) "sha256" +string(64) "d3a13cf52af8e9390caed78b77b6b1e06e102204e3555d111dfd149bc5d54dba" +string(64) "d3a13cf52af8e9390caed78b77b6b1e06e102204e3555d111dfd149bc5d54dba" +string(6) "sha384" +string(96) "6950d861ace4102b803ab8b3779d2f471968233010d2608974ab89804cef6f76162b4433d6e554e11e40a7cdcf510ea3" +string(96) "6950d861ace4102b803ab8b3779d2f471968233010d2608974ab89804cef6f76162b4433d6e554e11e40a7cdcf510ea3" +string(10) "sha512/224" +string(56) "a2573d0e3f6c3e2d174c935a35a8ea31032f04e9e83499ac3ceda568" +string(56) "a2573d0e3f6c3e2d174c935a35a8ea31032f04e9e83499ac3ceda568" +string(10) "sha512/256" +string(64) "fddacab80b3a610ba024c9d75a5fe0cafe5ae7c789f829b3c5fbea8ef11ccc1a" +string(64) "fddacab80b3a610ba024c9d75a5fe0cafe5ae7c789f829b3c5fbea8ef11ccc1a" +string(6) "sha512" +string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13" +string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13" +string(8) "sha3-224" +string(56) "7e1126cffee98e5c4b0e9dd5c6efabd5c9356d668e9a2d3cfab724d4" +string(56) "7e1126cffee98e5c4b0e9dd5c6efabd5c9356d668e9a2d3cfab724d4" +string(8) "sha3-256" +string(64) "834abfed9197af09cbe66b7748c65a050a3755ef7a556d6764eb6eabc93b4c7a" +string(64) "834abfed9197af09cbe66b7748c65a050a3755ef7a556d6764eb6eabc93b4c7a" +string(8) "sha3-384" +string(96) "c9016992586f7a8663c5379ed892349c1140ad258f7c44ee82f61f0b8cb75c675012ea94dc1314e06699be2d1465f67b" +string(96) "c9016992586f7a8663c5379ed892349c1140ad258f7c44ee82f61f0b8cb75c675012ea94dc1314e06699be2d1465f67b" +string(8) "sha3-512" +string(128) "5f85341bc9c6621406bf1841c4ce01727ea8759fdf2927106c3e70a75ad9fffd095b87f995aeee844e1a2c287e1195ce809b9bdb1c31258f7fc098175b6de0b4" +string(128) "5f85341bc9c6621406bf1841c4ce01727ea8759fdf2927106c3e70a75ad9fffd095b87f995aeee844e1a2c287e1195ce809b9bdb1c31258f7fc098175b6de0b4" +string(9) "ripemd128" +string(32) "5f1bc5f5aeaf747574dd34a6535cd94a" +string(32) "5f1bc5f5aeaf747574dd34a6535cd94a" +string(9) "ripemd160" +string(40) "02a2a535ee10404c6b5cf9acb178a04fbed67269" +string(40) "02a2a535ee10404c6b5cf9acb178a04fbed67269" +string(9) "ripemd256" +string(64) "547d2ed85ca0a0e3208b5ecf4fc6a7fc1e64db8ff13493e4beaf11e4d71648e2" +string(64) "547d2ed85ca0a0e3208b5ecf4fc6a7fc1e64db8ff13493e4beaf11e4d71648e2" +string(9) "ripemd320" +string(80) "785a7df56858f550966cddfd59ce14b13bf4b18e7892c4c1ad91bf23bf67639bd2c96749ba29cfa6" +string(80) "785a7df56858f550966cddfd59ce14b13bf4b18e7892c4c1ad91bf23bf67639bd2c96749ba29cfa6" +string(9) "whirlpool" +string(128) "6e60597340640e621e25f975cef2b000b0c4c09a7af7d240a52d193002b0a8426fa7da7acc5b37ed9608016d4f396db834a0ea2f2c35f900461c9ac7e5604082" +string(128) "6e60597340640e621e25f975cef2b000b0c4c09a7af7d240a52d193002b0a8426fa7da7acc5b37ed9608016d4f396db834a0ea2f2c35f900461c9ac7e5604082" +string(10) "tiger128,3" +string(32) "8d68e78bc5e62ba925a67aa48595cfc6" +string(32) "8d68e78bc5e62ba925a67aa48595cfc6" +string(10) "tiger160,3" +string(40) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e0" +string(40) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e0" +string(10) "tiger192,3" +string(48) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e08224fc35" +string(48) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e08224fc35" +string(10) "tiger128,4" +string(32) "a26ca3f58e74fb32ee44b099cb1b5122" +string(32) "a26ca3f58e74fb32ee44b099cb1b5122" +string(10) "tiger160,4" +string(40) "a26ca3f58e74fb32ee44b099cb1b512203375900" +string(40) "a26ca3f58e74fb32ee44b099cb1b512203375900" +string(10) "tiger192,4" +string(48) "a26ca3f58e74fb32ee44b099cb1b512203375900f30b741d" +string(48) "a26ca3f58e74fb32ee44b099cb1b512203375900f30b741d" +string(6) "snefru" +string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26" +string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26" +string(9) "snefru256" +string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26" +string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26" +string(4) "gost" +string(64) "5820c7c4a0650587538b30ef4099f2b5993069758d5c847a552e6ef7360766a5" +string(64) "5820c7c4a0650587538b30ef4099f2b5993069758d5c847a552e6ef7360766a5" +string(11) "gost-crypto" +string(64) "f7c4e35548d66aabe2b106f20515d289fde90969225d3d7b83f6dd12d694f043" +string(64) "f7c4e35548d66aabe2b106f20515d289fde90969225d3d7b83f6dd12d694f043" +string(7) "adler32" +string(8) "6f7c0928" +string(8) "6f7c0928" +string(5) "crc32" +string(8) "e5cfc160" +string(8) "e5cfc160" +string(6) "crc32b" +string(8) "69147a4e" +string(8) "69147a4e" +string(6) "crc32c" +string(8) "5e405e93" +string(8) "5e405e93" +string(6) "fnv132" +string(8) "98139504" +string(8) "98139504" +string(7) "fnv1a32" +string(8) "aae4e042" +string(8) "aae4e042" +string(6) "fnv164" +string(16) "14522659f8138684" +string(16) "14522659f8138684" +string(7) "fnv1a64" +string(16) "bebc746a33b6ab62" +string(16) "bebc746a33b6ab62" +string(5) "joaat" +string(8) "aaebf370" +string(8) "aaebf370" +string(10) "haval128,3" +string(32) "86362472c8895e68e223ef8b3711d8d9" +string(32) "86362472c8895e68e223ef8b3711d8d9" +string(10) "haval160,3" +string(40) "fabdf6905f3ba18a3c93d6a16b91e31f7222a7a4" +string(40) "fabdf6905f3ba18a3c93d6a16b91e31f7222a7a4" +string(10) "haval192,3" +string(48) "e05d0ff5723028bd5494f32c0c2494cd0b9ccf7540af7b47" +string(48) "e05d0ff5723028bd5494f32c0c2494cd0b9ccf7540af7b47" +string(10) "haval224,3" +string(56) "56b196289d8de8a22296588cf90e5b09cb6fa1b01ce8e92bca40cae2" +string(56) "56b196289d8de8a22296588cf90e5b09cb6fa1b01ce8e92bca40cae2" +string(10) "haval256,3" +string(64) "ff4d7ab0fac2ca437b945461f9b62fd16e71e9103524d5d140445a00e3d49239" +string(64) "ff4d7ab0fac2ca437b945461f9b62fd16e71e9103524d5d140445a00e3d49239" +string(10) "haval128,4" +string(32) "ee44418e0195a0c4a35d112722919a9c" +string(32) "ee44418e0195a0c4a35d112722919a9c" +string(10) "haval160,4" +string(40) "f320cce982d5201a1ccacc1c5ff835a258a97eb1" +string(40) "f320cce982d5201a1ccacc1c5ff835a258a97eb1" +string(10) "haval192,4" +string(48) "a96600107463e8e97a7fe6f260d9bf4f4587a281caafa6db" +string(48) "a96600107463e8e97a7fe6f260d9bf4f4587a281caafa6db" +string(10) "haval224,4" +string(56) "7147c9e1c1e67b942da3229f59a1ab18f121f5d7f5765ca88bc9f200" +string(56) "7147c9e1c1e67b942da3229f59a1ab18f121f5d7f5765ca88bc9f200" +string(10) "haval256,4" +string(64) "82fec42679ed5a77a841962827b88a9cddf7d677736e50bc81f1a14b99f06061" +string(64) "82fec42679ed5a77a841962827b88a9cddf7d677736e50bc81f1a14b99f06061" +string(10) "haval128,5" +string(32) "8d0b157828328ae7d34d60b4b60c1dab" +string(32) "8d0b157828328ae7d34d60b4b60c1dab" +string(10) "haval160,5" +string(40) "54dab5e10dc41503f9b8aa32ffe3bab7cf1da8a3" +string(40) "54dab5e10dc41503f9b8aa32ffe3bab7cf1da8a3" +string(10) "haval192,5" +string(48) "7d91265a1b27698279d8d95a5ee0a20014528070bf6415e7" +string(48) "7d91265a1b27698279d8d95a5ee0a20014528070bf6415e7" +string(10) "haval224,5" +string(56) "7772b2e22f2a3bce917e08cf57ebece46bb33168619a776c6f2f7234" +string(56) "7772b2e22f2a3bce917e08cf57ebece46bb33168619a776c6f2f7234" +string(10) "haval256,5" +string(64) "438a602cb1a761f7bd0a633b7bd8b3ccd0577b524d05174ca1ae1f559b9a2c2a" +string(64) "438a602cb1a761f7bd0a633b7bd8b3ccd0577b524d05174ca1ae1f559b9a2c2a" +string(3) "md2" +string(32) "5c36f61062d091a8324991132c5e8dbd" +string(32) "5c36f61062d091a8324991132c5e8dbd" +string(3) "md4" +string(32) "1d4196526aada3506efb4c7425651584" +string(32) "1d4196526aada3506efb4c7425651584" +string(3) "md5" +string(32) "f255c114bd6ce94aad092b5141c00d46" +string(32) "f255c114bd6ce94aad092b5141c00d46" +string(4) "sha1" +string(40) "a273396f056554dcd491b5dea1e7baa3b89b802b" +string(40) "a273396f056554dcd491b5dea1e7baa3b89b802b" +string(6) "sha224" +string(56) "1aee028400c56ceb5539625dc2f395abf491409336ca0f3e177a50e2" +string(56) "1aee028400c56ceb5539625dc2f395abf491409336ca0f3e177a50e2" +string(6) "sha256" +string(64) "268e7f4cf88504a53fd77136c4c4748169f46ff7150b376569ada9c374836944" +string(64) "268e7f4cf88504a53fd77136c4c4748169f46ff7150b376569ada9c374836944" +string(6) "sha384" +string(96) "0d44981d04bb11b1ef75d5c2932bd0aa2785e7bc454daac954d77e2ca10047879b58997533fc99650b20049c6cb9a6cc" +string(96) "0d44981d04bb11b1ef75d5c2932bd0aa2785e7bc454daac954d77e2ca10047879b58997533fc99650b20049c6cb9a6cc" +string(10) "sha512/224" +string(56) "cbc2bbf0028ed803af785b0f264962c84ec48d8ee0908322ef995ddb" +string(56) "cbc2bbf0028ed803af785b0f264962c84ec48d8ee0908322ef995ddb" +string(10) "sha512/256" +string(64) "2cec704878ffa7128e0c4a61eef87d1f3c823184d364dfa3fed73beb00499b00" +string(64) "2cec704878ffa7128e0c4a61eef87d1f3c823184d364dfa3fed73beb00499b00" +string(6) "sha512" +string(128) "28d7c721433782a880f840af0c3f3ea2cad4ef55de2114dda9d504cedeb110e1cf2519c49e4b5da3da4484bb6ba4fd1621ceadc6408f4410b2ebe9d83a4202c2" +string(128) "28d7c721433782a880f840af0c3f3ea2cad4ef55de2114dda9d504cedeb110e1cf2519c49e4b5da3da4484bb6ba4fd1621ceadc6408f4410b2ebe9d83a4202c2" +string(8) "sha3-224" +string(56) "9a21a5464794c2c9784df50cf89cf72234e11941bddaee93f912753e" +string(56) "9a21a5464794c2c9784df50cf89cf72234e11941bddaee93f912753e" +string(8) "sha3-256" +string(64) "57aa7a90f29b5ab66592760592780da247fd39b4c911773687450f9df8cc8ed0" +string(64) "57aa7a90f29b5ab66592760592780da247fd39b4c911773687450f9df8cc8ed0" +string(8) "sha3-384" +string(96) "5d6d7e42b241288bc707b74c50f90a37d69a4afa854ca72021a22cb379356e53b6233aea1be2f33d393d6effa9b5e36c" +string(96) "5d6d7e42b241288bc707b74c50f90a37d69a4afa854ca72021a22cb379356e53b6233aea1be2f33d393d6effa9b5e36c" +string(8) "sha3-512" +string(128) "9b88c689bc13a36e6983b32e8ee9464d63b619f246ca451d1fe2a6c9670f01e71d0c8eb245f3204d27d27c056f2a0fef76a1e3bc30fb74cccbc984dbd4883ae6" +string(128) "9b88c689bc13a36e6983b32e8ee9464d63b619f246ca451d1fe2a6c9670f01e71d0c8eb245f3204d27d27c056f2a0fef76a1e3bc30fb74cccbc984dbd4883ae6" +string(9) "ripemd128" +string(32) "f95f5e22b8875ee0c48219ae97f0674b" +string(32) "f95f5e22b8875ee0c48219ae97f0674b" +string(9) "ripemd160" +string(40) "900d615c1abe714e340f4ecd6a3d65599fd30ff4" +string(40) "900d615c1abe714e340f4ecd6a3d65599fd30ff4" +string(9) "ripemd256" +string(64) "b9799db40d1af5614118c329169cdcd2c718db6af03bf945ea7f7ba72b8e14f4" +string(64) "b9799db40d1af5614118c329169cdcd2c718db6af03bf945ea7f7ba72b8e14f4" +string(9) "ripemd320" +string(80) "d6d12c1fca7a9c4a59c1be4f40188e92a746a035219e0a6ca1ee53b36a8282527187f7dffaa57ecc" +string(80) "d6d12c1fca7a9c4a59c1be4f40188e92a746a035219e0a6ca1ee53b36a8282527187f7dffaa57ecc" +string(9) "whirlpool" +string(128) "e8c6a921e7d8eac2fd21d4df6054bb27a02321b2beb5b01b6f88c40706164e64d67ec97519bf76c8af8df896745478b78d42a0159f1a0db16777771fd9d420dc" +string(128) "e8c6a921e7d8eac2fd21d4df6054bb27a02321b2beb5b01b6f88c40706164e64d67ec97519bf76c8af8df896745478b78d42a0159f1a0db16777771fd9d420dc" +string(10) "tiger128,3" +string(32) "a99d2c0348d480dc0f3c35852926e0f1" +string(32) "a99d2c0348d480dc0f3c35852926e0f1" +string(10) "tiger160,3" +string(40) "a99d2c0348d480dc0f3c35852926e0f1e1825c16" +string(40) "a99d2c0348d480dc0f3c35852926e0f1e1825c16" +string(10) "tiger192,3" +string(48) "a99d2c0348d480dc0f3c35852926e0f1e1825c1651957ee3" +string(48) "a99d2c0348d480dc0f3c35852926e0f1e1825c1651957ee3" +string(10) "tiger128,4" +string(32) "66e2c0322421c4e5a9208e6aeed481e5" +string(32) "66e2c0322421c4e5a9208e6aeed481e5" +string(10) "tiger160,4" +string(40) "66e2c0322421c4e5a9208e6aeed481e5c4b00448" +string(40) "66e2c0322421c4e5a9208e6aeed481e5c4b00448" +string(10) "tiger192,4" +string(48) "66e2c0322421c4e5a9208e6aeed481e5c4b00448e344d9d0" +string(48) "66e2c0322421c4e5a9208e6aeed481e5c4b00448e344d9d0" +string(6) "snefru" +string(64) "614ca924864fa0e8fa309aa0944e047d5edbfd4964a35858f4d8ec66a0fb88b0" +string(64) "614ca924864fa0e8fa309aa0944e047d5edbfd4964a35858f4d8ec66a0fb88b0" +string(9) "snefru256" +string(64) "614ca924864fa0e8fa309aa0944e047d5edbfd4964a35858f4d8ec66a0fb88b0" +string(64) "614ca924864fa0e8fa309aa0944e047d5edbfd4964a35858f4d8ec66a0fb88b0" +string(4) "gost" +string(64) "a00961e371287c71c527a41c14564f13b6ed12ac7cd9d5f5dfb3542a25e28d3b" +string(64) "a00961e371287c71c527a41c14564f13b6ed12ac7cd9d5f5dfb3542a25e28d3b" +string(11) "gost-crypto" +string(64) "68ca9aea6729dc07d995fbe071a4b5c6490bb27fc4dc65ec0e96200d5e082996" +string(64) "68ca9aea6729dc07d995fbe071a4b5c6490bb27fc4dc65ec0e96200d5e082996" +string(7) "adler32" +string(8) "d9141747" +string(8) "d9141747" +string(5) "crc32" +string(8) "59f8d3d2" +string(8) "59f8d3d2" +string(6) "crc32b" +string(8) "3ee63999" +string(8) "3ee63999" +string(6) "crc32c" +string(8) "516ad412" +string(8) "516ad412" +string(6) "fnv132" +string(8) "59ad036f" +string(8) "59ad036f" +string(7) "fnv1a32" +string(8) "fadc2cef" +string(8) "fadc2cef" +string(6) "fnv164" +string(16) "5e8c64fba6a5ffcf" +string(16) "5e8c64fba6a5ffcf" +string(7) "fnv1a64" +string(16) "893899e4415a920f" +string(16) "893899e4415a920f" +string(5) "joaat" +string(8) "836fb0e5" +string(8) "836fb0e5" +string(10) "haval128,3" +string(32) "ebeeeb05c18af1e53d2d127b561d5e0d" +string(32) "ebeeeb05c18af1e53d2d127b561d5e0d" +string(10) "haval160,3" +string(40) "f1a2c9604fb40899ad502abe0dfcec65115c8a9a" +string(40) "f1a2c9604fb40899ad502abe0dfcec65115c8a9a" +string(10) "haval192,3" +string(48) "d3a7315773a326678208650ed02510ed96cd488d74cd5231" +string(48) "d3a7315773a326678208650ed02510ed96cd488d74cd5231" +string(10) "haval224,3" +string(56) "6d7132fabc83c9ab7913748b79ecf10e25409569d3ed144177f46731" +string(56) "6d7132fabc83c9ab7913748b79ecf10e25409569d3ed144177f46731" +string(10) "haval256,3" +string(64) "7a469868ad4b92891a3a44524c58a2b8d0f3bebb92b4cf47d19bc6aba973eb95" +string(64) "7a469868ad4b92891a3a44524c58a2b8d0f3bebb92b4cf47d19bc6aba973eb95" +string(10) "haval128,4" +string(32) "6ecddb39615f43fd211839287ff38461" +string(32) "6ecddb39615f43fd211839287ff38461" +string(10) "haval160,4" +string(40) "bcd2e7821723ac22e122b8b7cbbd2daaa9a862df" +string(40) "bcd2e7821723ac22e122b8b7cbbd2daaa9a862df" +string(10) "haval192,4" +string(48) "ae74619a88dcec1fbecde28e27f009a65ecc12170824d2cd" +string(48) "ae74619a88dcec1fbecde28e27f009a65ecc12170824d2cd" +string(10) "haval224,4" +string(56) "fdaba6563f1334d40de24e311f14b324577f97c3b78b9439c408cdca" +string(56) "fdaba6563f1334d40de24e311f14b324577f97c3b78b9439c408cdca" +string(10) "haval256,4" +string(64) "289a2ba4820218bdb25a6534fbdf693f9de101362584fdd41e32244c719caa37" +string(64) "289a2ba4820218bdb25a6534fbdf693f9de101362584fdd41e32244c719caa37" +string(10) "haval128,5" +string(32) "ffa7993a4e183b245263fb1f63e27343" +string(32) "ffa7993a4e183b245263fb1f63e27343" +string(10) "haval160,5" +string(40) "375ee5ab3a9bd07a1dbe5d071e07b2afb3165e3b" +string(40) "375ee5ab3a9bd07a1dbe5d071e07b2afb3165e3b" +string(10) "haval192,5" +string(48) "c650585f93c6e041e835caedc621f8c42d8bc6829fb76789" +string(48) "c650585f93c6e041e835caedc621f8c42d8bc6829fb76789" +string(10) "haval224,5" +string(56) "bc674d465a822817d939f19b38edde083fe5668759836c203c56e3e4" +string(56) "bc674d465a822817d939f19b38edde083fe5668759836c203c56e3e4" +string(10) "haval256,5" +string(64) "da70ad9bd09ed7c9675329ea2b5279d57761807c7aeac6340d94b5d494809457" +string(64) "da70ad9bd09ed7c9675329ea2b5279d57761807c7aeac6340d94b5d494809457" +Done diff --git a/ext/hash/tests/hash_serialize_002.phpt b/ext/hash/tests/hash_serialize_002.phpt new file mode 100644 index 0000000000..b6b4ccfb5e --- /dev/null +++ b/ext/hash/tests/hash_serialize_002.phpt @@ -0,0 +1,116 @@ +--TEST-- +Hash: serialize()/unserialize() with HASH_HMAC +--FILE-- +<?php + +$algos = hash_algos(); +$non_crypto = ["adler32", "crc32", "crc32b", "crc32c", "fnv132", "fnv1a32", "fnv164", "fnv1a64", "joaat"]; +$key = "This is the key that I have"; + +foreach ($algos as $algo) { + if (in_array($algo, $non_crypto)) { + continue; + } + + var_dump($algo); + $ctx0 = hash_init($algo, HASH_HMAC, $key); + try { + $serial = serialize($ctx0); + assert(is_string($serial)); + } catch (Throwable $e) { + echo $e->getMessage(), "\n"; + } +} + +echo "Done\n"; +?> +--EXPECT-- +string(3) "md2" +HashContext with HASH_HMAC option cannot be serialized +string(3) "md4" +HashContext with HASH_HMAC option cannot be serialized +string(3) "md5" +HashContext with HASH_HMAC option cannot be serialized +string(4) "sha1" +HashContext with HASH_HMAC option cannot be serialized +string(6) "sha224" +HashContext with HASH_HMAC option cannot be serialized +string(6) "sha256" +HashContext with HASH_HMAC option cannot be serialized +string(6) "sha384" +HashContext with HASH_HMAC option cannot be serialized +string(10) "sha512/224" +HashContext with HASH_HMAC option cannot be serialized +string(10) "sha512/256" +HashContext with HASH_HMAC option cannot be serialized +string(6) "sha512" +HashContext with HASH_HMAC option cannot be serialized +string(8) "sha3-224" +HashContext with HASH_HMAC option cannot be serialized +string(8) "sha3-256" +HashContext with HASH_HMAC option cannot be serialized +string(8) "sha3-384" +HashContext with HASH_HMAC option cannot be serialized +string(8) "sha3-512" +HashContext with HASH_HMAC option cannot be serialized +string(9) "ripemd128" +HashContext with HASH_HMAC option cannot be serialized +string(9) "ripemd160" +HashContext with HASH_HMAC option cannot be serialized +string(9) "ripemd256" +HashContext with HASH_HMAC option cannot be serialized +string(9) "ripemd320" +HashContext with HASH_HMAC option cannot be serialized +string(9) "whirlpool" +HashContext with HASH_HMAC option cannot be serialized +string(10) "tiger128,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "tiger160,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "tiger192,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "tiger128,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "tiger160,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "tiger192,4" +HashContext with HASH_HMAC option cannot be serialized +string(6) "snefru" +HashContext with HASH_HMAC option cannot be serialized +string(9) "snefru256" +HashContext with HASH_HMAC option cannot be serialized +string(4) "gost" +HashContext with HASH_HMAC option cannot be serialized +string(11) "gost-crypto" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval128,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval160,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval192,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval224,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval256,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval128,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval160,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval192,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval224,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval256,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval128,5" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval160,5" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval192,5" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval224,5" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval256,5" +HashContext with HASH_HMAC option cannot be serialized +Done diff --git a/ext/hash/tests/hash_serialize_003.phpt b/ext/hash/tests/hash_serialize_003.phpt new file mode 100644 index 0000000000..a687c2aeff --- /dev/null +++ b/ext/hash/tests/hash_serialize_003.phpt @@ -0,0 +1,261 @@ +--TEST-- +Hash: serialization formats +--FILE-- +<?php + +$serializations = [ + [ + "md2", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjM6Im1kMiI7aToxO2k6MDtpOjI7YTo0OntpOjA7czo0ODoiuyJG48A1rdYMPXAiWBDcbOrPsUaDg8lhMXhr/DQfjaN7dOqrImXTxBykKAln5L8sIjtpOjE7czoxNjoiwrfjcIJR1I8RljMyAxmcSyI7aToyO3M6MTY6IiBhbnl0aGluZwAAAAAAAAAiO2k6MztpOjk7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "md4", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjM6Im1kNCI7aToxO2k6MDtpOjI7YTo3OntpOjA7aToxNzMyNTg0MTkzO2k6MTtpOi0yNzE3MzM4Nzk7aToyO2k6LTE3MzI1ODQxOTQ7aTozO2k6MjcxNzMzODc4O2k6NDtpOjIwMDtpOjU7aTowO2k6NjtzOjY0OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIjt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "md5", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjM6Im1kNSI7aToxO2k6MDtpOjI7YToyMzp7aTowO2k6MjU7aToxO2k6MDtpOjI7aToxNzMyNTg0MTkzO2k6MztpOi0yNzE3MzM4Nzk7aTo0O2k6LTE3MzI1ODQxOTQ7aTo1O2k6MjcxNzMzODc4O2k6NjtzOjY0OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIjtpOjc7aTowO2k6ODtpOjA7aTo5O2k6MDtpOjEwO2k6MDtpOjExO2k6MDtpOjEyO2k6MDtpOjEzO2k6MDtpOjE0O2k6MDtpOjE1O2k6MDtpOjE2O2k6MDtpOjE3O2k6MDtpOjE4O2k6MDtpOjE5O2k6MDtpOjIwO2k6MDtpOjIxO2k6MDtpOjIyO2k6MDt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "sha1", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6InNoYTEiO2k6MTtpOjA7aToyO2E6ODp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aTotMTAwOTU4OTc3NjtpOjU7aToyMDA7aTo2O2k6MDtpOjc7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "sha224", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjY6InNoYTIyNCI7aToxO2k6MDtpOjI7YToxMTp7aTowO2k6LTEwNTY1OTYyNjQ7aToxO2k6OTE0MTUwNjYzO2k6MjtpOjgxMjcwMjk5OTtpOjM7aTotMTUwMDU0NTk5O2k6NDtpOi00MTkxNDM5O2k6NTtpOjE3NTA2MDMwMjU7aTo2O2k6MTY5NDA3NjgzOTtpOjc7aTotMTA5MDg5MTg2ODtpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6NjQ6IkkgY2FuJ3QgcmVtZW1iZXIgYW55dGhpbmcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO31pOjM7aToyO2k6NDthOjA6e319" + ], + [ + "sha256", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjY6InNoYTI1NiI7aToxO2k6MDtpOjI7YToxMTp7aTowO2k6MTc3OTAzMzcwMztpOjE7aTotMTE1MDgzMzAxOTtpOjI7aToxMDEzOTA0MjQyO2k6MztpOi0xNTIxNDg2NTM0O2k6NDtpOjEzNTk4OTMxMTk7aTo1O2k6LTE2OTQxNDQzNzI7aTo2O2k6NTI4NzM0NjM1O2k6NztpOjE1NDE0NTkyMjU7aTo4O2k6MjAwO2k6OTtpOjA7aToxMDtzOjY0OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIjt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "sha384", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjY6InNoYTM4NCI7aToxO2k6MDtpOjI7YToyMTp7aTowO2k6LTEwNTY1OTYyNjQ7aToxO2k6LTg3Njg5NjkzMTtpOjI7aTo5MTQxNTA2NjM7aTozO2k6MTY1NDI3MDI1MDtpOjQ7aTo4MTI3MDI5OTk7aTo1O2k6LTE4NTY0Mzc5MjY7aTo2O2k6LTE1MDA1NDU5OTtpOjc7aTozNTU0NjIzNjA7aTo4O2k6LTQxOTE0Mzk7aTo5O2k6MTczMTQwNTQxNTtpOjEwO2k6MTc1MDYwMzAyNTtpOjExO2k6LTE5MDA3ODcwNjU7aToxMjtpOjE2OTQwNzY4Mzk7aToxMztpOi02MTk5NTg3NzE7aToxNDtpOi0xMDkwODkxODY4O2k6MTU7aToxMjAzMDYyODEzO2k6MTY7aToyMDA7aToxNztpOjA7aToxODtpOjA7aToxOTtpOjA7aToyMDtzOjEyODoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO31pOjM7aToyO2k6NDthOjA6e319" + ], + [ + "sha512/224", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJzaGE1MTIvMjI0IjtpOjE7aTowO2k6MjthOjIxOntpOjA7aTo0MjQ5NTUyOTg7aToxO2k6LTE5NDIxNDUwODA7aToyO2k6LTE5ODIwMTYyOTg7aTozO2k6MTk0NDE2NDcxMDtpOjQ7aTo4NTU2MTI1NDY7aTo1O2k6NTAyOTcwMjg2O2k6NjtpOjE0Nzk1MTYxMTE7aTo3O2k6MTczODM5Njk0ODtpOjg7aToyMDc3NTExMDgwO2k6OTtpOjI1ODgxMjc3NztpOjEwO2k6Nzk5ODkwNTg7aToxMTtpOjIwMTEzOTM5MDc7aToxMjtpOjE3ODAyOTk0NjQ7aToxMztpOjEwNjcyODc5NzY7aToxNDtpOi0xODQ4MjA4NzM1O2k6MTU7aToyODY0NTEzNzM7aToxNjtpOjIwMDtpOjE3O2k6MDtpOjE4O2k6MDtpOjE5O2k6MDtpOjIwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "sha512/256", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJzaGE1MTIvMjU2IjtpOjE7aTowO2k6MjthOjIxOntpOjA7aTotNjQyMjc1NDA7aToxO2k6NTczNjQ1MjA0O2k6MjtpOi05MzQ1MTc1NjY7aTozO2k6LTE2MjE3OTQ5MDk7aTo0O2k6MTg2Nzc1NTg1NztpOjU7aTo1OTY4ODM1NjM7aTo2O2k6MTQ5NzQyNjYyMTtpOjc7aTotMTc3NDY4NDM5MTtpOjg7aTotMTQ2NzAyMzM4OTtpOjk7aTotMTc3NTc0NzM1ODtpOjEwO2k6MTQwMTMwNTQ5MDtpOjExO2k6LTExMDExMjgxNTU7aToxMjtpOjc0Njk2MTA2NjtpOjEzO2k6NzIxNTI1MjQ0O2k6MTQ7aTotMjExNzc4NDQxNDtpOjE1O2k6MjQ2ODg1ODUyO2k6MTY7aToyMDA7aToxNztpOjA7aToxODtpOjA7aToxOTtpOjA7aToyMDtzOjEyODoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO31pOjM7aToyO2k6NDthOjA6e319" + ], + [ + "sha512", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjY6InNoYTUxMiI7aToxO2k6MDtpOjI7YToyMTp7aTowO2k6LTIwNTczMTU3NjtpOjE7aToxNzc5MDMzNzAzO2k6MjtpOi0yMDY3MDkzNzAxO2k6MztpOi0xMTUwODMzMDE5O2k6NDtpOi0yMzc5MTU3MztpOjU7aToxMDEzOTA0MjQyO2k6NjtpOjE1OTU3NTAxMjk7aTo3O2k6LTE1MjE0ODY1MzQ7aTo4O2k6LTEzNzc0MDIxNTk7aTo5O2k6MTM1OTg5MzExOTtpOjEwO2k6NzI1NTExMTk5O2k6MTE7aTotMTY5NDE0NDM3MjtpOjEyO2k6LTc5NTc3NzQ5O2k6MTM7aTo1Mjg3MzQ2MzU7aToxNDtpOjMyNzAzMzIwOTtpOjE1O2k6MTU0MTQ1OTIyNTtpOjE2O2k6MjAwO2k6MTc7aTowO2k6MTg7aTowO2k6MTk7aTowO2k6MjA7czoxMjg6IkkgY2FuJ3QgcmVtZW1iZXIgYW55dGhpbmcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIjt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "ripemd128", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjk6InJpcGVtZDEyOCI7aToxO2k6MDtpOjI7YTo3OntpOjA7aToxNzMyNTg0MTkzO2k6MTtpOi0yNzE3MzM4Nzk7aToyO2k6LTE3MzI1ODQxOTQ7aTozO2k6MjcxNzMzODc4O2k6NDtpOjIwMDtpOjU7aTowO2k6NjtzOjY0OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIjt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "ripemd160", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjk6InJpcGVtZDE2MCI7aToxO2k6MDtpOjI7YTo4OntpOjA7aToxNzMyNTg0MTkzO2k6MTtpOi0yNzE3MzM4Nzk7aToyO2k6LTE3MzI1ODQxOTQ7aTozO2k6MjcxNzMzODc4O2k6NDtpOi0xMDA5NTg5Nzc2O2k6NTtpOjIwMDtpOjY7aTowO2k6NztzOjY0OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIjt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "ripemd256", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjk6InJpcGVtZDI1NiI7aToxO2k6MDtpOjI7YToxMTp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aToxOTg1MjI5MzI4O2k6NTtpOi0xOTA4ODc0NDtpOjY7aTotMTk4NTIyOTMyOTtpOjc7aToxOTA4ODc0MztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6NjQ6IkkgY2FuJ3QgcmVtZW1iZXIgYW55dGhpbmcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO31pOjM7aToyO2k6NDthOjA6e319" + ], + [ + "ripemd320", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjk6InJpcGVtZDMyMCI7aToxO2k6MDtpOjI7YToxMzp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aTotMTAwOTU4OTc3NjtpOjU7aToxOTg1MjI5MzI4O2k6NjtpOi0xOTA4ODc0NDtpOjc7aTotMTk4NTIyOTMyOTtpOjg7aToxOTA4ODc0MztpOjk7aToxMDA5NTg5Nzc1O2k6MTA7aToyMDA7aToxMTtpOjA7aToxMjtzOjY0OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIjt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "whirlpool", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjk6IndoaXJscG9vbCI7aToxO2k6MDtpOjI7YToyMDp7aTowO2k6MDtpOjE7aTowO2k6MjtpOjA7aTozO2k6MDtpOjQ7aTowO2k6NTtpOjA7aTo2O2k6MDtpOjc7aTowO2k6ODtpOjA7aTo5O2k6MDtpOjEwO2k6MDtpOjExO2k6MDtpOjEyO2k6MDtpOjEzO2k6MDtpOjE0O2k6MDtpOjE1O2k6MDtpOjE2O3M6MzI6IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADIIjtpOjE3O2k6MjU7aToxODtpOjIwMDtpOjE5O3M6NjQ6IkkgY2FuJ3QgcmVtZW1iZXIgYW55dGhpbmcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO31pOjM7aToyO2k6NDthOjA6e319" + ], + [ + "tiger128,3", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJ0aWdlcjEyOCwzIjtpOjE7aTowO2k6MjthOjEwOntpOjA7aTotMTk4NTIyOTMyOTtpOjE7aToxOTA4ODc0MztpOjI7aToxOTg1MjI5MzI4O2k6MztpOi0xOTA4ODc0NDtpOjQ7aTotMTAxMTY4NzAzMztpOjU7aTotMjU4NTYyNjM2O2k6NjtpOjA7aTo3O2k6MDtpOjg7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7aTo5O2k6MjU7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "tiger160,3", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJ0aWdlcjE2MCwzIjtpOjE7aTowO2k6MjthOjEwOntpOjA7aTotMTk4NTIyOTMyOTtpOjE7aToxOTA4ODc0MztpOjI7aToxOTg1MjI5MzI4O2k6MztpOi0xOTA4ODc0NDtpOjQ7aTotMTAxMTY4NzAzMztpOjU7aTotMjU4NTYyNjM2O2k6NjtpOjA7aTo3O2k6MDtpOjg7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7aTo5O2k6MjU7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "tiger192,3", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJ0aWdlcjE5MiwzIjtpOjE7aTowO2k6MjthOjEwOntpOjA7aTotMTk4NTIyOTMyOTtpOjE7aToxOTA4ODc0MztpOjI7aToxOTg1MjI5MzI4O2k6MztpOi0xOTA4ODc0NDtpOjQ7aTotMTAxMTY4NzAzMztpOjU7aTotMjU4NTYyNjM2O2k6NjtpOjA7aTo3O2k6MDtpOjg7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7aTo5O2k6MjU7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "tiger128,4", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJ0aWdlcjEyOCw0IjtpOjE7aTowO2k6MjthOjEwOntpOjA7aTotMTk4NTIyOTMyOTtpOjE7aToxOTA4ODc0MztpOjI7aToxOTg1MjI5MzI4O2k6MztpOi0xOTA4ODc0NDtpOjQ7aTotMTAxMTY4NzAzMztpOjU7aTotMjU4NTYyNjM2O2k6NjtpOjA7aTo3O2k6MDtpOjg7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7aTo5O2k6MjU7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "tiger160,4", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJ0aWdlcjE2MCw0IjtpOjE7aTowO2k6MjthOjEwOntpOjA7aTotMTk4NTIyOTMyOTtpOjE7aToxOTA4ODc0MztpOjI7aToxOTg1MjI5MzI4O2k6MztpOi0xOTA4ODc0NDtpOjQ7aTotMTAxMTY4NzAzMztpOjU7aTotMjU4NTYyNjM2O2k6NjtpOjA7aTo3O2k6MDtpOjg7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7aTo5O2k6MjU7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "tiger192,4", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJ0aWdlcjE5Miw0IjtpOjE7aTowO2k6MjthOjEwOntpOjA7aTotMTk4NTIyOTMyOTtpOjE7aToxOTA4ODc0MztpOjI7aToxOTg1MjI5MzI4O2k6MztpOi0xOTA4ODc0NDtpOjQ7aTotMTAxMTY4NzAzMztpOjU7aTotMjU4NTYyNjM2O2k6NjtpOjA7aTo3O2k6MDtpOjg7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7aTo5O2k6MjU7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "snefru", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjY6InNuZWZydSI7aToxO2k6MDtpOjI7YToyMDp7aTowO2k6MDtpOjE7aTowO2k6MjtpOjA7aTozO2k6MDtpOjQ7aTowO2k6NTtpOjA7aTo2O2k6MDtpOjc7aTowO2k6ODtpOjA7aTo5O2k6MDtpOjEwO2k6MDtpOjExO2k6MDtpOjEyO2k6MDtpOjEzO2k6MDtpOjE0O2k6MDtpOjE1O2k6MDtpOjE2O2k6MDtpOjE3O2k6MjAwO2k6MTg7aToyNTtpOjE5O3M6MzI6IkkgY2FuJ3QgcmVtZW1iZXIgYW55dGhpbmcAAAAAAAAAIjt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "snefru256", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjY6InNuZWZydSI7aToxO2k6MDtpOjI7YToyMDp7aTowO2k6MDtpOjE7aTowO2k6MjtpOjA7aTozO2k6MDtpOjQ7aTowO2k6NTtpOjA7aTo2O2k6MDtpOjc7aTowO2k6ODtpOjA7aTo5O2k6MDtpOjEwO2k6MDtpOjExO2k6MDtpOjEyO2k6MDtpOjEzO2k6MDtpOjE0O2k6MDtpOjE1O2k6MDtpOjE2O2k6MDtpOjE3O2k6MjAwO2k6MTg7aToyNTtpOjE5O3M6MzI6IkkgY2FuJ3QgcmVtZW1iZXIgYW55dGhpbmcAAAAAAAAAIjt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "gost", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6Imdvc3QiO2k6MTtpOjA7aToyO2E6MjA6e2k6MDtpOjA7aToxO2k6MDtpOjI7aTowO2k6MztpOjA7aTo0O2k6MDtpOjU7aTowO2k6NjtpOjA7aTo3O2k6MDtpOjg7aTowO2k6OTtpOjA7aToxMDtpOjA7aToxMTtpOjA7aToxMjtpOjA7aToxMztpOjA7aToxNDtpOjA7aToxNTtpOjA7aToxNjtpOjIwMDtpOjE3O2k6MDtpOjE4O2k6MjU7aToxOTtzOjMyOiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "gost-crypto", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjExOiJnb3N0LWNyeXB0byI7aToxO2k6MDtpOjI7YToyMDp7aTowO2k6MDtpOjE7aTowO2k6MjtpOjA7aTozO2k6MDtpOjQ7aTowO2k6NTtpOjA7aTo2O2k6MDtpOjc7aTowO2k6ODtpOjA7aTo5O2k6MDtpOjEwO2k6MDtpOjExO2k6MDtpOjEyO2k6MDtpOjEzO2k6MDtpOjE0O2k6MDtpOjE1O2k6MDtpOjE2O2k6MjAwO2k6MTc7aTowO2k6MTg7aToyNTtpOjE5O3M6MzI6IkkgY2FuJ3QgcmVtZW1iZXIgYW55dGhpbmcAAAAAAAAAIjt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "adler32", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjc6ImFkbGVyMzIiO2k6MTtpOjA7aToyO2E6MTp7aTowO2k6MTg3MDM5OTc4NDt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "crc32", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjU6ImNyYzMyIjtpOjE7aTowO2k6MjthOjE6e2k6MDtpOi0xNjIzMzE0NDA2O31pOjM7aToyO2k6NDthOjA6e319" + ], + [ + "crc32b", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjY6ImNyYzMyYiI7aToxO2k6MDtpOjI7YToxOntpOjA7aTotMTc2Mjk0OTcxMTt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "crc32c", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjY6ImNyYzMyYyI7aToxO2k6MDtpOjI7YToxOntpOjA7aTotMTU4MTI3NjgyMDt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "fnv132", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjY6ImZudjEzMiI7aToxO2k6MDtpOjI7YToxOntpOjA7aTotMTc0MzU0NzEzMjt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "fnv1a32", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjc6ImZudjFhMzIiO2k6MTtpOjA7aToyO2E6MTp7aTowO2k6LTE0Mjc4NDA5NTg7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "fnv164", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjY6ImZudjE2NCI7aToxO2k6MDtpOjI7YToyOntpOjA7aTotMTMyOTM4MTA4O2k6MTtpOjM0MDkyODA4OTt9aTozO2k6MjtpOjQ7YTowOnt9fQ==" + ], + [ + "fnv1a64", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjc6ImZudjFhNjQiO2k6MTtpOjA7aToyO2E6Mjp7aTowO2k6ODY3NjA5NDQyO2k6MTtpOi0xMDk0OTQ1Njg2O31pOjM7aToyO2k6NDthOjA6e319" + ], + [ + "joaat", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjU6ImpvYWF0IjtpOjE7aTowO2k6MjthOjE6e2k6MDtpOi0xNDY5OTExMTA7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval128,3", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDEyOCwzIjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval160,3", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDE2MCwzIjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval192,3", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDE5MiwzIjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval224,3", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDIyNCwzIjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval256,3", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDI1NiwzIjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval128,4", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDEyOCw0IjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval160,4", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDE2MCw0IjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval192,4", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDE5Miw0IjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval224,4", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDIyNCw0IjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval256,4", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDI1Niw0IjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval128,5", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDEyOCw1IjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval160,5", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDE2MCw1IjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval192,5", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDE5Miw1IjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval224,5", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDIyNCw1IjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "haval256,5", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjEwOiJoYXZhbDI1Niw1IjtpOjE7aTowO2k6MjthOjExOntpOjA7aTo2MDgxMzU4MTY7aToxO2k6LTIwNTI5MTI5NDE7aToyO2k6MzIwNDQwODc4O2k6MztpOjU3NzAxMTg4O2k6NDtpOi0xNTQyODk5Njc4O2k6NTtpOjY5ODI5ODgzMjtpOjY7aToxMzcyOTY1MzY7aTo3O2k6LTMzMDQwNDcyNztpOjg7aToyMDA7aTo5O2k6MDtpOjEwO3M6MTI4OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" + ], + [ + "sha3-224", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjg6InNoYTMtMjI0IjtpOjE7aTowO2k6MjthOjI6e2k6MDtzOjIwMDoiSSBjYW4ndCCNmpKakp2ajd+ekYaLl5aRZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO2k6MTtpOjI1O31pOjM7aToxMDA7aTo0O2E6MDp7fX0=", /* 64-bit fast LE */ + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjg6InNoYTMtMjI0IjtpOjE7aTowO2k6MjthOjI6e2k6MDtzOjIwMDoiCZk6DkJFV0S8u4vLRUZWVJDajqlEZ2R2CwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO2k6MTtpOjI1O31pOjM7aToxMDE7aTo0O2E6MDp7fX0=", /* 32-bit fast LE */ + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjg6InNoYTMtMjI0IjtpOjE7aTowO2k6MjthOjI6e2k6MDtzOjIwMDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO2k6MTtpOjI1O31pOjM7aToyO2k6NDthOjA6e319" /* slow */ + ], + [ + "sha3-256", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjg6InNoYTMtMjU2IjtpOjE7aTowO2k6MjthOjI6e2k6MDtzOjIwMDoiSSBjYW4ndCCNmpKakp2ajd+ekYaLl5aRZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO2k6MTtpOjI1O31pOjM7aToxMDA7aTo0O2E6MDp7fX0=", /* 64-bit fast LE */ + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjg6InNoYTMtMjU2IjtpOjE7aTowO2k6MjthOjI6e2k6MDtzOjIwMDoiCZk6DkJFV0S8u4vLRUZWVJDajqlEZ2R2CwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO2k6MTtpOjI1O31pOjM7aToxMDE7aTo0O2E6MDp7fX0=", /* 32-bit fast LE */ + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjg6InNoYTMtMjU2IjtpOjE7aTowO2k6MjthOjI6e2k6MDtzOjIwMDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO2k6MTtpOjI1O31pOjM7aToyO2k6NDthOjA6e319" /* slow */ + ], + [ + "sha3-384", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjg6InNoYTMtMzg0IjtpOjE7aTowO2k6MjthOjI6e2k6MDtzOjIwMDoiSSBjYW4ndCCNmpKakp2ajd+ekYaLl5aRZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO2k6MTtpOjI1O31pOjM7aToxMDA7aTo0O2E6MDp7fX0=", /* 64-bit fast LE */ + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjg6InNoYTMtMzg0IjtpOjE7aTowO2k6MjthOjI6e2k6MDtzOjIwMDoiCZk6DkJFV0S8u4vLRUZWVJDajqlEZ2R2CwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO2k6MTtpOjI1O31pOjM7aToxMDE7aTo0O2E6MDp7fX0=", /* 32-bit fast LE */ + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjg6InNoYTMtMzg0IjtpOjE7aTowO2k6MjthOjI6e2k6MDtzOjIwMDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO2k6MTtpOjI1O31pOjM7aToyO2k6NDthOjA6e319" /* slow */ + ], + [ + "sha3-512", + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjg6InNoYTMtNTEyIjtpOjE7aTowO2k6MjthOjI6e2k6MDtzOjIwMDoiSSBjYW4ndCCNmpKakp2ajd+ekYaLl5aRZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO2k6MTtpOjI1O31pOjM7aToxMDA7aTo0O2E6MDp7fX0=", /* 64-bit fast LE */ + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjg6InNoYTMtNTEyIjtpOjE7aTowO2k6MjthOjI6e2k6MDtzOjIwMDoiCZk6DkJFV0S8u4vLRUZWVJDajqlEZ2R2CwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO2k6MTtpOjI1O31pOjM7aToxMDE7aTo0O2E6MDp7fX0=", /* 32-bit fast LE */ + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjg6InNoYTMtNTEyIjtpOjE7aTowO2k6MjthOjI6e2k6MDtzOjIwMDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiO2k6MTtpOjI1O31pOjM7aToyO2k6NDthOjA6e319" /* slow */ + ] +]; + + +function test_serialization($serial, $hash, $algo) { + try { + $ctx = unserialize(base64_decode($serial)); + hash_update($ctx, "Can’t tell if this is true or dream"); + $hash2 = hash_final($ctx); + if ($hash !== $hash2) { + echo "$algo: unexpected hash $hash2 for serialization {$serial}\n"; + } + } catch (Throwable $e) { + echo "$algo: problem with serialization {$serial}\n"; + echo " ", $e->getMessage(), "\n", $e->getTraceAsString(); + } +} + +foreach ($serializations as $slist) { + $algo = $slist[0]; + $hash = hash($algo, "I can't remember anythingCan’t tell if this is true or dream"); + + $ctx = hash_init($algo); + hash_update($ctx, "I can't remember anything"); + $serial = base64_encode(serialize($ctx)); + if (!in_array($serial, $slist)) { + echo "$algo: unexpected serialization $serial\n"; + } + + test_serialization($serial, $hash, $algo); +} + +echo "Done\n"; +?> +--EXPECT-- +Done diff --git a/ext/hash/tests/hash_serialize_004.phpt b/ext/hash/tests/hash_serialize_004.phpt new file mode 100644 index 0000000000..ee5c08f973 --- /dev/null +++ b/ext/hash/tests/hash_serialize_004.phpt @@ -0,0 +1,45 @@ +--TEST-- +Hash: serialization errors +--FILE-- +<?php + +// cannot unserialize onto an already-initialized object +$ctx = hash_init("sha256"); +try { + $ctx->__unserialize($ctx->__serialize()); +} catch (Exception $e) { + echo $e->getMessage(), "\n"; +} + +// bad formats +foreach ([ + "TzoxMToiSGFzaENvbnRleHQiOjA6e30=", // no contents + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtpOjE7aToxO2k6MDtpOjI7YTo4OntpOjA7aToxNzMyNTg0MTkzO2k6MTtpOi0yNzE3MzM4Nzk7aToyO2k6LTE3MzI1ODQxOTQ7aTozO2k6MjcxNzMzODc4O2k6NDtpOi0xMDA5NTg5Nzc2O2k6NTtpOjIwMDtpOjY7aTowO2k6NztzOjY0OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIjt9aTozO2k6MjtpOjQ7YTowOnt9fQ==", // algorithm is int + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6InNoYTEiO2k6MTtzOjA6IiI7aToyO2E6ODp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aTotMTAwOTU4OTc3NjtpOjU7aToyMDA7aTo2O2k6MDtpOjc7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=", // flags are string + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6InNoYTEiO2k6MTtpOjE7aToyO2E6ODp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aTotMTAwOTU4OTc3NjtpOjU7aToyMDA7aTo2O2k6MDtpOjc7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=", // flags indicate HASH_HMAC + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6InNoYTEiO2k6MTtpOjI7aToyO3M6MTA6ImFiY2RlZmdoaWoiO2k6MztpOjI7aTo0O2E6MDp7fX0=", // serialization format wrong + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6InNoYTEiO2k6MTtpOjA7aToyO2E6ODp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aTotMTAwOTU4OTc3NjtpOjU7aToyMDA7aTo2O3M6MDoiIjtpOjc7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=", // serialization internals wrong + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6InNoYTEiO2k6MTtpOjA7aToyO2E6ODp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aTotMTAwOTU4OTc3NjtpOjU7aToyMDA7aTo2O2k6MDtpOjc7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjA7aTo0O2E6MDp7fX0=", // bad magic number + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6Inh4eDEiO2k6MTtpOjA7aToyO2E6ODp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aTotMTAwOTU4OTc3NjtpOjU7aToyMDA7aTo2O2k6MDtpOjc7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" // bad algorithm +] as $serial) { + try { + $ctx = unserialize(base64_decode($serial)); + echo "Unexpected success\n"; + } catch (Exception $e) { + echo $e->getMessage(), "\n"; + } +} + +echo "Done\n"; +?> +--EXPECT-- +HashContext::__unserialize called on initialized object +Incomplete or ill-formed serialization data +Incomplete or ill-formed serialization data +Incomplete or ill-formed serialization data +HashContext with HASH_HMAC option cannot be serialized +Incomplete or ill-formed serialization data ("sha1" code -1) +Incomplete or ill-formed serialization data ("sha1" code -1024) +Incomplete or ill-formed serialization data ("sha1" code -1) +Unknown hash algorithm +Done diff --git a/ext/hash/tests/serialize-context.phpt b/ext/hash/tests/serialize-context.phpt deleted file mode 100644 index 32aa0ab806..0000000000 --- a/ext/hash/tests/serialize-context.phpt +++ /dev/null @@ -1,13 +0,0 @@ ---TEST-- -Hash: Context serialization ---FILE-- -<?php - -$h = hash_init('md5'); -try { - var_dump(serialize($h)); -} catch (Exception $e) { - echo "Exception: {$e->getMessage()}\n"; -} ---EXPECT-- -Exception: Serialization of 'HashContext' is not allowed diff --git a/ext/standard/md5.h b/ext/standard/md5.h index 15417990d7..ac60d7fca4 100644 --- a/ext/standard/md5.h +++ b/ext/standard/md5.h @@ -40,6 +40,7 @@ typedef struct { unsigned char buffer[64]; uint32_t block[16]; } PHP_MD5_CTX; +#define PHP_MD5_SPEC "llllllb64l16." PHPAPI void PHP_MD5Init(PHP_MD5_CTX *ctx); PHPAPI void PHP_MD5Update(PHP_MD5_CTX *ctx, const void *data, size_t size); diff --git a/ext/standard/sha1.h b/ext/standard/sha1.h index c904969dd3..ef98ecc29c 100644 --- a/ext/standard/sha1.h +++ b/ext/standard/sha1.h @@ -25,6 +25,7 @@ typedef struct { uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_SHA1_CTX; +#define PHP_SHA1_SPEC "l5l2b64." PHPAPI void PHP_SHA1Init(PHP_SHA1_CTX *); PHPAPI void PHP_SHA1Update(PHP_SHA1_CTX *, const unsigned char *, size_t); |