@@ -4720,7 +4720,16 @@ void Hash::Initialize(Environment* env, Local<Object> target) {
47204720void Hash::New (const FunctionCallbackInfo<Value>& args) {
47214721 Environment* env = Environment::GetCurrent (args);
47224722
4723- const node::Utf8Value hash_type (env->isolate (), args[0 ]);
4723+ const Hash* orig = nullptr ;
4724+ const EVP_MD* md = nullptr ;
4725+
4726+ if (args[0 ]->IsObject ()) {
4727+ ASSIGN_OR_RETURN_UNWRAP (&orig, args[0 ].As <Object>());
4728+ md = EVP_MD_CTX_md (orig->mdctx_ .get ());
4729+ } else {
4730+ const node::Utf8Value hash_type (env->isolate (), args[0 ]);
4731+ md = EVP_get_digestbyname (*hash_type);
4732+ }
47244733
47254734 Maybe<unsigned int > xof_md_len = Nothing<unsigned int >();
47264735 if (!args[1 ]->IsUndefined ()) {
@@ -4729,17 +4738,19 @@ void Hash::New(const FunctionCallbackInfo<Value>& args) {
47294738 }
47304739
47314740 Hash* hash = new Hash (env, args.This ());
4732- if (!hash->HashInit (*hash_type , xof_md_len)) {
4741+ if (md == nullptr || !hash->HashInit (md , xof_md_len)) {
47334742 return ThrowCryptoError (env, ERR_get_error (),
47344743 " Digest method not supported" );
47354744 }
4745+
4746+ if (orig != nullptr &&
4747+ 0 >= EVP_MD_CTX_copy (hash->mdctx_ .get (), orig->mdctx_ .get ())) {
4748+ return ThrowCryptoError (env, ERR_get_error (), " Digest copy error" );
4749+ }
47364750}
47374751
47384752
4739- bool Hash::HashInit (const char * hash_type, Maybe<unsigned int > xof_md_len) {
4740- const EVP_MD* md = EVP_get_digestbyname (hash_type);
4741- if (md == nullptr )
4742- return false ;
4753+ bool Hash::HashInit (const EVP_MD* md, Maybe<unsigned int > xof_md_len) {
47434754 mdctx_.reset (EVP_MD_CTX_new ());
47444755 if (!mdctx_ || EVP_DigestInit_ex (mdctx_.get (), md, nullptr ) <= 0 ) {
47454756 mdctx_.reset ();
0 commit comments