| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent cab905f commit 5dd72a6
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1041,6 +1041,43 @@ console.log(hash.digest('hex')); | |||
| 1041 | 1041 | // 6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50 | |
| 1042 | 1042 | ``` | |
| 1043 | 1043 | ||
| 1044 | + ### `hash.copy([options])` | ||
| 1045 | + <!-- YAML | ||
| 1046 | + added: | ||
| 1047 | + - version: REPLACEME | ||
| 1048 | + pr-url: https://github.com/nodejs/node/pull/29910 | ||
| 1049 | + --> | ||
| 1050 | + | ||
| 1051 | + * `options` {Object} [`stream.transform` options][] | ||
| 1052 | + * Returns: {Hash} | ||
| 1053 | + | ||
| 1054 | + Creates a new `Hash` object that contains a deep copy of the internal state | ||
| 1055 | + of the current `Hash` object. | ||
| 1056 | + | ||
| 1057 | + The optional `options` argument controls stream behavior. For XOF hash | ||
| 1058 | + functions such as `'shake256'`, the `outputLength` option can be used to | ||
| 1059 | + specify the desired output length in bytes. | ||
| 1060 | + | ||
| 1061 | + An error is thrown when an attempt is made to copy the `Hash` object after | ||
| 1062 | + its [`hash.digest()`][] method has been called. | ||
| 1063 | + | ||
| 1064 | + ```js | ||
| 1065 | + // Calculate a rolling hash. | ||
| 1066 | + const crypto = require('crypto'); | ||
| 1067 | + const hash = crypto.createHash('sha256'); | ||
| 1068 | + | ||
| 1069 | + hash.update('one'); | ||
| 1070 | + console.log(hash.copy().digest('hex')); | ||
| 1071 | + | ||
| 1072 | + hash.update('two'); | ||
| 1073 | + console.log(hash.copy().digest('hex')); | ||
| 1074 | + | ||
| 1075 | + hash.update('three'); | ||
| 1076 | + console.log(hash.copy().digest('hex')); | ||
| 1077 | + | ||
| 1078 | + // Etc. | ||
| 1079 | + ``` | ||
| 1080 | + | ||
| 1044 | 1081 | ### `hash.digest([encoding])` | |
| 1045 | 1082 | <!-- YAML | |
| 1046 | 1083 | added: v0.1.92 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -36,7 +36,8 @@ const kFinalized = Symbol('kFinalized'); | |||
| 36 | 36 | function Hash(algorithm, options) { | |
| 37 | 37 | if (!(this instanceof Hash)) | |
| 38 | 38 | return new Hash(algorithm, options); | |
| 39 | - validateString(algorithm, 'algorithm'); | ||
| 39 | + if (!(algorithm instanceof _Hash)) | ||
| 40 | + validateString(algorithm, 'algorithm'); | ||
| 40 | 41 | const xofLen = typeof options === 'object' && options !== null ? | |
| 41 | 42 | options.outputLength : undefined; | |
| 42 | 43 | if (xofLen !== undefined) | |
@@ -51,6 +52,14 @@ function Hash(algorithm, options) { | |||
| 51 | 52 | Object.setPrototypeOf(Hash.prototype, LazyTransform.prototype); | |
| 52 | 53 | Object.setPrototypeOf(Hash, LazyTransform); | |
| 53 | 54 | ||
| 55 | + Hash.prototype.copy = function copy(options) { | ||
| 56 | + const state = this[kState]; | ||
| 57 | + if (state[kFinalized]) | ||
| 58 | + throw new ERR_CRYPTO_HASH_FINALIZED(); | ||
| 59 | + | ||
| 60 | + return new Hash(this[kHandle], options); | ||
| 61 | + }; | ||
| 62 | + | ||
| 54 | 63 | Hash.prototype._transform = function _transform(chunk, encoding, callback) { | |
| 55 | 64 | this[kHandle].update(chunk, encoding); | |
| 56 | 65 | callback(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4721,7 +4721,16 @@ void Hash::Initialize(Environment* env, Local<Object> target) { | |||
| 4721 | 4721 | void Hash::New(const FunctionCallbackInfo<Value>& args) { | |
| 4722 | 4722 | Environment* env = Environment::GetCurrent(args); | |
| 4723 | 4723 | ||
| 4724 | - const node::Utf8Value hash_type(env->isolate(), args[0]); | ||
| 4724 | + const Hash* orig = nullptr; | ||
| 4725 | + const EVP_MD* md = nullptr; | ||
| 4726 | + | ||
| 4727 | + if (args[0]->IsObject()) { | ||
| 4728 | + ASSIGN_OR_RETURN_UNWRAP(&orig, args[0].As<Object>()); | ||
| 4729 | + md = EVP_MD_CTX_md(orig->mdctx_.get()); | ||
| 4730 | + } else { | ||
| 4731 | + const node::Utf8Value hash_type(env->isolate(), args[0]); | ||
| 4732 | + md = EVP_get_digestbyname(*hash_type); | ||
| 4733 | + } | ||
| 4725 | 4734 | ||
| 4726 | 4735 | Maybe<unsigned int> xof_md_len = Nothing<unsigned int>(); | |
| 4727 | 4736 | if (!args[1]->IsUndefined()) { | |
@@ -4730,17 +4739,19 @@ void Hash::New(const FunctionCallbackInfo<Value>& args) { | |||
| 4730 | 4739 | } | |
| 4731 | 4740 | ||
| 4732 | 4741 | Hash* hash = new Hash(env, args.This()); | |
| 4733 | - if (!hash->HashInit(*hash_type, xof_md_len)) { | ||
| 4742 | + if (md == nullptr || !hash->HashInit(md, xof_md_len)) { | ||
| 4734 | 4743 | return ThrowCryptoError(env, ERR_get_error(), | |
| 4735 | 4744 | "Digest method not supported"); | |
| 4736 | 4745 | } | |
| 4746 | + | ||
| 4747 | + if (orig != nullptr && | ||
| 4748 | + 0 >= EVP_MD_CTX_copy(hash->mdctx_.get(), orig->mdctx_.get())) { | ||
| 4749 | + return ThrowCryptoError(env, ERR_get_error(), "Digest copy error"); | ||
| 4750 | + } | ||
| 4737 | 4751 | } | |
| 4738 | 4752 | ||
| 4739 | 4753 | ||
| 4740 | - bool Hash::HashInit(const char* hash_type, Maybe<unsigned int> xof_md_len) { | ||
| 4741 | - const EVP_MD* md = EVP_get_digestbyname(hash_type); | ||
| 4742 | - if (md == nullptr) | ||
| 4743 | - return false; | ||
| 4754 | + bool Hash::HashInit(const EVP_MD* md, Maybe<unsigned int> xof_md_len) { | ||
| 4744 | 4755 | mdctx_.reset(EVP_MD_CTX_new()); | |
| 4745 | 4756 | if (!mdctx_ || EVP_DigestInit_ex(mdctx_.get(), md, nullptr) <= 0) { | |
| 4746 | 4757 | mdctx_.reset(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -591,7 +591,7 @@ class Hash : public BaseObject { | |||
| 591 | 591 | SET_MEMORY_INFO_NAME(Hash) | |
| 592 | 592 | SET_SELF_SIZE(Hash) | |
| 593 | 593 | ||
| 594 | - bool HashInit(const char* hash_type, v8::Maybe<unsigned int> xof_md_len); | ||
| 594 | + bool HashInit(const EVP_MD* md, v8::Maybe<unsigned int> xof_md_len); | ||
| 595 | 595 | bool HashUpdate(const char* data, int len); | |
| 596 | 596 | ||
| 597 | 597 | protected: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -192,14 +192,27 @@ common.expectsError( | |||
| 192 | 192 | assert.strictEqual(crypto.createHash('shake256').digest('hex'), | |
| 193 | 193 | '46b9dd2b0ba88d13233b3feb743eeb24' + | |
| 194 | 194 | '3fcd52ea62b81b82b50c27646ed5762f'); | |
| 195 | + assert.strictEqual(crypto.createHash('shake256', { outputLength: 0 }) | ||
| 196 | + .copy() // Default outputLength. | ||
| 197 | + .digest('hex'), | ||
| 198 | + '46b9dd2b0ba88d13233b3feb743eeb24' + | ||
| 199 | + '3fcd52ea62b81b82b50c27646ed5762f'); | ||
| 195 | 200 | ||
| 196 | 201 | // Short outputLengths. | |
| 197 | 202 | assert.strictEqual(crypto.createHash('shake128', { outputLength: 0 }) | |
| 198 | 203 | .digest('hex'), | |
| 199 | 204 | ''); | |
| 205 | + assert.strictEqual(crypto.createHash('shake128', { outputLength: 5 }) | ||
| 206 | + .copy({ outputLength: 0 }) | ||
| 207 | + .digest('hex'), | ||
| 208 | + ''); | ||
| 200 | 209 | assert.strictEqual(crypto.createHash('shake128', { outputLength: 5 }) | |
| 201 | 210 | .digest('hex'), | |
| 202 | 211 | '7f9c2ba4e8'); | |
| 212 | + assert.strictEqual(crypto.createHash('shake128', { outputLength: 0 }) | ||
| 213 | + .copy({ outputLength: 5 }) | ||
| 214 | + .digest('hex'), | ||
| 215 | + '7f9c2ba4e8'); | ||
| 203 | 216 | assert.strictEqual(crypto.createHash('shake128', { outputLength: 15 }) | |
| 204 | 217 | .digest('hex'), | |
| 205 | 218 | '7f9c2ba4e88f827d61604550760585'); | |
@@ -249,3 +262,19 @@ common.expectsError( | |||
| 249 | 262 | { code: 'ERR_OUT_OF_RANGE' }); | |
| 250 | 263 | } | |
| 251 | 264 | } | |
| 265 | + | ||
| 266 | + { | ||
| 267 | + const h = crypto.createHash('sha512'); | ||
| 268 | + h.digest(); | ||
| 269 | + common.expectsError(() => h.copy(), { code: 'ERR_CRYPTO_HASH_FINALIZED' }); | ||
| 270 | + common.expectsError(() => h.digest(), { code: 'ERR_CRYPTO_HASH_FINALIZED' }); | ||
| 271 | + } | ||
| 272 | + | ||
| 273 | + { | ||
| 274 | + const a = crypto.createHash('sha512').update('abc'); | ||
| 275 | + const b = a.copy(); | ||
| 276 | + const c = b.copy().update('def'); | ||
| 277 | + const d = crypto.createHash('sha512').update('abcdef'); | ||
| 278 | + assert.strictEqual(a.digest('hex'), b.digest('hex')); | ||
| 279 | + assert.strictEqual(c.digest('hex'), d.digest('hex')); | ||
| 280 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments