@@ -4718,7 +4718,16 @@ void Hash::Initialize(Environment* env, Local<Object> target) {
47184718void Hash::New (const FunctionCallbackInfo<Value>& args) {
47194719 Environment* env = Environment::GetCurrent (args);
47204720
4721- const node::Utf8Value hash_type (env->isolate (), args[0 ]);
4721+ const Hash* orig = nullptr ;
4722+ const EVP_MD* md = nullptr ;
4723+
4724+ if (args[0 ]->IsObject ()) {
4725+ ASSIGN_OR_RETURN_UNWRAP (&orig, args[0 ].As <Object>());
4726+ md = EVP_MD_CTX_md (orig->mdctx_ .get ());
4727+ } else {
4728+ const node::Utf8Value hash_type (env->isolate (), args[0 ]);
4729+ md = EVP_get_digestbyname (*hash_type);
4730+ }
47224731
47234732 Maybe<unsigned int > xof_md_len = Nothing<unsigned int >();
47244733 if (!args[1 ]->IsUndefined ()) {
@@ -4727,17 +4736,19 @@ void Hash::New(const FunctionCallbackInfo<Value>& args) {
47274736 }
47284737
47294738 Hash* hash = new Hash (env, args.This ());
4730- if (!hash->HashInit (*hash_type , xof_md_len)) {
4739+ if (md == nullptr || !hash->HashInit (md , xof_md_len)) {
47314740 return ThrowCryptoError (env, ERR_get_error (),
47324741 " Digest method not supported" );
47334742 }
4743+
4744+ if (orig != nullptr &&
4745+ 0 >= EVP_MD_CTX_copy (hash->mdctx_ .get (), orig->mdctx_ .get ())) {
4746+ return ThrowCryptoError (env, ERR_get_error (), " Digest copy error" );
4747+ }
47344748}
47354749
47364750
4737- bool Hash::HashInit (const char * hash_type, Maybe<unsigned int > xof_md_len) {
4738- const EVP_MD* md = EVP_get_digestbyname (hash_type);
4739- if (md == nullptr )
4740- return false ;
4751+ bool Hash::HashInit (const EVP_MD* md, Maybe<unsigned int > xof_md_len) {
47414752 mdctx_.reset (EVP_MD_CTX_new ());
47424753 if (!mdctx_ || EVP_DigestInit_ex (mdctx_.get (), md, nullptr ) <= 0 ) {
47434754 mdctx_.reset ();
0 commit comments