diff --git a/lib/internal/crypto/sig.js b/lib/internal/crypto/sig.js index 52827c9c4b2..9f1938290f7 100644 --- a/lib/internal/crypto/sig.js +++ b/lib/internal/crypto/sig.js @@ -13,12 +13,15 @@ const { getDefaultEncoding, toBuf } = require('internal/crypto/util'); +const { isArrayBufferView } = require('internal/util/types'); const { Writable } = require('stream'); const { inherits } = require('util'); function Sign(algorithm, options) { if (!(this instanceof Sign)) return new Sign(algorithm, options); + if (typeof algorithm !== 'string') + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'algorithm', 'string'); this._handle = new _Sign(); this._handle.init(algorithm); @@ -28,13 +31,18 @@ function Sign(algorithm, options) { inherits(Sign, Writable); Sign.prototype._write = function _write(chunk, encoding, callback) { - this._handle.update(chunk, encoding); + this.update(chunk, encoding); callback(); }; Sign.prototype.update = function update(data, encoding) { encoding = encoding || getDefaultEncoding(); - this._handle.update(data, encoding); + data = toBuf(data, encoding); + if (!isArrayBufferView(data)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'data', + ['string', 'Buffer', 'TypedArray', 'DataView']); + } + this._handle.update(data); return this; }; @@ -68,8 +76,13 @@ Sign.prototype.sign = function sign(options, encoding) { } } - var ret = this._handle.sign(toBuf(key), passphrase, rsaPadding, - pssSaltLength); + key = toBuf(key); + if (!isArrayBufferView(key)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'key', + ['string', 'Buffer', 'TypedArray', 'DataView']); + } + + var ret = this._handle.sign(key, passphrase, rsaPadding, pssSaltLength); encoding = encoding || getDefaultEncoding(); if (encoding && encoding !== 'buffer') @@ -82,7 +95,8 @@ Sign.prototype.sign = function sign(options, encoding) { function Verify(algorithm, options) { if (!(this instanceof Verify)) return new Verify(algorithm, options); - + if (typeof algorithm !== 'string') + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'algorithm', 'string'); this._handle = new _Verify(); this._handle.init(algorithm); @@ -121,8 +135,19 @@ Verify.prototype.verify = function verify(options, signature, sigEncoding) { } } - return this._handle.verify(toBuf(key), toBuf(signature, sigEncoding), - rsaPadding, pssSaltLength); + key = toBuf(key); + if (!isArrayBufferView(key)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'key', + ['string', 'Buffer', 'TypedArray', 'DataView']); + } + + signature = toBuf(signature, sigEncoding); + if (!isArrayBufferView(signature)) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'signature', + ['string', 'Buffer', 'TypedArray', 'DataView']); + } + + return this._handle.verify(key, signature, rsaPadding, pssSaltLength); }; module.exports = { diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 3e8dd4205f2..7decd7dd182 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -4036,13 +4036,6 @@ SignBase::Error Sign::SignInit(const char* sign_type) { void Sign::SignInit(const FunctionCallbackInfo& args) { Sign* sign; ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder()); - Environment* env = sign->env(); - - if (args.Length() == 0) { - return env->ThrowError("Sign type argument is mandatory"); - } - - THROW_AND_RETURN_IF_NOT_STRING(args[0], "Sign type"); const node::Utf8Value sign_type(args.GetIsolate(), args[0]); sign->CheckThrow(sign->SignInit(*sign_type)); @@ -4059,25 +4052,13 @@ SignBase::Error Sign::SignUpdate(const char* data, int len) { void Sign::SignUpdate(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - Sign* sign; ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder()); - THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(args[0], "Data"); - - // Only copy the data if we have to, because it's a string Error err; - if (args[0]->IsString()) { - StringBytes::InlineDecoder decoder; - if (!decoder.Decode(env, args[0].As(), args[1], UTF8)) - return; - err = sign->SignUpdate(decoder.out(), decoder.size()); - } else { - char* buf = Buffer::Data(args[0]); - size_t buflen = Buffer::Length(args[0]); - err = sign->SignUpdate(buf, buflen); - } + char* buf = Buffer::Data(args[0]); + size_t buflen = Buffer::Length(args[0]); + err = sign->SignUpdate(buf, buflen); sign->CheckThrow(err); } @@ -4195,7 +4176,6 @@ void Sign::SignFinal(const FunctionCallbackInfo& args) { node::Utf8Value passphrase(env->isolate(), args[1]); - THROW_AND_RETURN_IF_NOT_BUFFER(args[0], "Data"); size_t buf_len = Buffer::Length(args[0]); char* buf = Buffer::Data(args[0]); @@ -4269,13 +4249,6 @@ SignBase::Error Verify::VerifyInit(const char* verify_type) { void Verify::VerifyInit(const FunctionCallbackInfo& args) { Verify* verify; ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder()); - Environment* env = verify->env(); - - if (args.Length() == 0) { - return env->ThrowError("Verify type argument is mandatory"); - } - - THROW_AND_RETURN_IF_NOT_STRING(args[0], "Verify type"); const node::Utf8Value verify_type(args.GetIsolate(), args[0]); verify->CheckThrow(verify->VerifyInit(*verify_type)); @@ -4294,25 +4267,13 @@ SignBase::Error Verify::VerifyUpdate(const char* data, int len) { void Verify::VerifyUpdate(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - Verify* verify; ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder()); - THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(args[0], "Data"); - - // Only copy the data if we have to, because it's a string Error err; - if (args[0]->IsString()) { - StringBytes::InlineDecoder decoder; - if (!decoder.Decode(env, args[0].As(), args[1], UTF8)) - return; - err = verify->VerifyUpdate(decoder.out(), decoder.size()); - } else { - char* buf = Buffer::Data(args[0]); - size_t buflen = Buffer::Length(args[0]); - err = verify->VerifyUpdate(buf, buflen); - } + char* buf = Buffer::Data(args[0]); + size_t buflen = Buffer::Length(args[0]); + err = verify->VerifyUpdate(buf, buflen); verify->CheckThrow(err); } @@ -4421,12 +4382,9 @@ void Verify::VerifyFinal(const FunctionCallbackInfo& args) { Verify* verify; ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder()); - THROW_AND_RETURN_IF_NOT_BUFFER(args[0], "Key"); char* kbuf = Buffer::Data(args[0]); ssize_t klen = Buffer::Length(args[0]); - THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(args[1], "Hash"); - char* hbuf = Buffer::Data(args[1]); ssize_t hlen = Buffer::Length(args[1]); diff --git a/test/parallel/test-crypto-sign-verify.js b/test/parallel/test-crypto-sign-verify.js index 18a09a99393..5f0f8d8c7eb 100644 --- a/test/parallel/test-crypto-sign-verify.js +++ b/test/parallel/test-crypto-sign-verify.js @@ -277,3 +277,106 @@ const modSize = 1024; assert(stdout.includes('Verified OK')); })); } + +[1, [], {}, undefined, null, true, Infinity].forEach((i) => { + common.expectsError( + () => crypto.createSign(), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "algorithm" argument must be of type string' + } + ); + common.expectsError( + () => crypto.createVerify(), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "algorithm" argument must be of type string' + } + ); +}); + +{ + const sign = crypto.createSign('SHA1'); + const verify = crypto.createVerify('SHA1'); + + [1, [], {}, undefined, null, true, Infinity].forEach((i) => { + common.expectsError( + () => sign.update(i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "data" argument must be one of type string, Buffer, ' + + 'TypedArray, or DataView' + } + ); + common.expectsError( + () => verify.update(i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "data" argument must be one of type string, Buffer, ' + + 'TypedArray, or DataView' + } + ); + common.expectsError( + () => sign._write(i, 'utf8', () => {}), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "data" argument must be one of type string, Buffer, ' + + 'TypedArray, or DataView' + } + ); + common.expectsError( + () => verify._write(i, 'utf8', () => {}), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "data" argument must be one of type string, Buffer, ' + + 'TypedArray, or DataView' + } + ); + }); + + [ + Uint8Array, Uint16Array, Uint32Array, Float32Array, Float64Array + ].forEach((i) => { + // These should all just work + sign.update(new i()); + verify.update(new i()); + }); + + [1, {}, [], Infinity].forEach((i) => { + common.expectsError( + () => sign.sign(i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "key" argument must be one of type string, Buffer, ' + + 'TypedArray, or DataView' + } + ); + + common.expectsError( + () => verify.verify(i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "key" argument must be one of type string, Buffer, ' + + 'TypedArray, or DataView' + } + ); + + common.expectsError( + () => verify.verify('test', i), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "signature" argument must be one of type string, ' + + 'Buffer, TypedArray, or DataView' + } + ); + }); +} diff --git a/test/parallel/test-crypto.js b/test/parallel/test-crypto.js index d501991dd2f..76164c683f9 100644 --- a/test/parallel/test-crypto.js +++ b/test/parallel/test-crypto.js @@ -201,28 +201,6 @@ assert.throws(function() { } }); -assert.throws(function() { - crypto.createSign('SHA1').update('0', 'hex'); -}, (err) => { - // Throws TypeError, so there is no opensslErrorStack property. - if ((err instanceof Error) && - /^TypeError: Bad input string$/.test(err) && - err.opensslErrorStack === undefined) { - return true; - } -}); - -assert.throws(function() { - crypto.createVerify('SHA1').update('0', 'hex'); -}, (err) => { - // Throws TypeError, so there is no opensslErrorStack property. - if ((err instanceof Error) && - /^TypeError: Bad input string$/.test(err) && - err.opensslErrorStack === undefined) { - return true; - } -}); - assert.throws(function() { const priv = [ '-----BEGIN RSA PRIVATE KEY-----',