crypto: refactor array buffer view validation
This is just a refactoring to reduce code and computational overhead. PR-URL: https://github.com/nodejs/node/pull/29683 Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
204248a0c3
commit
eb05d68815
@ -9,11 +9,8 @@ const {
|
|||||||
validateBuffer
|
validateBuffer
|
||||||
} = require('internal/validators');
|
} = require('internal/validators');
|
||||||
|
|
||||||
const { ERR_INVALID_ARG_TYPE } = require('internal/errors').codes;
|
|
||||||
const { isArrayBufferView } = require('internal/util/types');
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
toBuf
|
getArrayBufferView
|
||||||
} = require('internal/crypto/util');
|
} = require('internal/crypto/util');
|
||||||
|
|
||||||
function verifySpkac(spkac) {
|
function verifySpkac(spkac) {
|
||||||
@ -22,27 +19,15 @@ function verifySpkac(spkac) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function exportPublicKey(spkac, encoding) {
|
function exportPublicKey(spkac, encoding) {
|
||||||
spkac = toBuf(spkac, encoding);
|
return certExportPublicKey(
|
||||||
if (!isArrayBufferView(spkac)) {
|
getArrayBufferView(spkac, 'spkac', encoding)
|
||||||
throw new ERR_INVALID_ARG_TYPE(
|
|
||||||
'spkac',
|
|
||||||
['string', 'Buffer', 'TypedArray', 'DataView'],
|
|
||||||
spkac
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
return certExportPublicKey(spkac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function exportChallenge(spkac, encoding) {
|
function exportChallenge(spkac, encoding) {
|
||||||
spkac = toBuf(spkac, encoding);
|
return certExportChallenge(
|
||||||
if (!isArrayBufferView(spkac)) {
|
getArrayBufferView(spkac, 'spkac', encoding)
|
||||||
throw new ERR_INVALID_ARG_TYPE(
|
|
||||||
'spkac',
|
|
||||||
['string', 'Buffer', 'TypedArray', 'DataView'],
|
|
||||||
spkac
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
return certExportChallenge(spkac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For backwards compatibility reasons, this cannot be converted into a
|
// For backwards compatibility reasons, this cannot be converted into a
|
||||||
|
@ -22,7 +22,7 @@ const {
|
|||||||
const {
|
const {
|
||||||
getDefaultEncoding,
|
getDefaultEncoding,
|
||||||
kHandle,
|
kHandle,
|
||||||
toBuf
|
getArrayBufferView
|
||||||
} = require('internal/crypto/util');
|
} = require('internal/crypto/util');
|
||||||
|
|
||||||
const { isArrayBufferView } = require('internal/util/types');
|
const { isArrayBufferView } = require('internal/util/types');
|
||||||
@ -105,20 +105,9 @@ function createCipherBase(cipher, credential, options, decipher, iv) {
|
|||||||
LazyTransform.call(this, options);
|
LazyTransform.call(this, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
function invalidArrayBufferView(name, value) {
|
|
||||||
return new ERR_INVALID_ARG_TYPE(
|
|
||||||
name,
|
|
||||||
['string', 'Buffer', 'TypedArray', 'DataView'],
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createCipher(cipher, password, options, decipher) {
|
function createCipher(cipher, password, options, decipher) {
|
||||||
validateString(cipher, 'cipher');
|
validateString(cipher, 'cipher');
|
||||||
password = toBuf(password);
|
password = getArrayBufferView(password, 'password');
|
||||||
if (!isArrayBufferView(password)) {
|
|
||||||
throw invalidArrayBufferView('password', password);
|
|
||||||
}
|
|
||||||
|
|
||||||
createCipherBase.call(this, cipher, password, options, decipher);
|
createCipherBase.call(this, cipher, password, options, decipher);
|
||||||
}
|
}
|
||||||
@ -126,10 +115,7 @@ function createCipher(cipher, password, options, decipher) {
|
|||||||
function createCipherWithIV(cipher, key, options, decipher, iv) {
|
function createCipherWithIV(cipher, key, options, decipher, iv) {
|
||||||
validateString(cipher, 'cipher');
|
validateString(cipher, 'cipher');
|
||||||
key = prepareSecretKey(key);
|
key = prepareSecretKey(key);
|
||||||
iv = toBuf(iv);
|
iv = iv === null ? null : getArrayBufferView(iv, 'iv');
|
||||||
if (iv !== null && !isArrayBufferView(iv)) {
|
|
||||||
throw invalidArrayBufferView('iv', iv);
|
|
||||||
}
|
|
||||||
createCipherBase.call(this, cipher, key, options, decipher, iv);
|
createCipherBase.call(this, cipher, key, options, decipher, iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +150,8 @@ Cipher.prototype.update = function update(data, inputEncoding, outputEncoding) {
|
|||||||
outputEncoding = outputEncoding || encoding;
|
outputEncoding = outputEncoding || encoding;
|
||||||
|
|
||||||
if (typeof data !== 'string' && !isArrayBufferView(data)) {
|
if (typeof data !== 'string' && !isArrayBufferView(data)) {
|
||||||
throw invalidArrayBufferView('data', data);
|
throw new ERR_INVALID_ARG_TYPE(
|
||||||
|
'data', ['string', 'Buffer', 'TypedArray', 'DataView'], data);
|
||||||
}
|
}
|
||||||
|
|
||||||
validateEncoding(data, inputEncoding);
|
validateEncoding(data, inputEncoding);
|
||||||
|
@ -13,7 +13,7 @@ const {
|
|||||||
} = require('internal/errors').codes;
|
} = require('internal/errors').codes;
|
||||||
const {
|
const {
|
||||||
getDefaultEncoding,
|
getDefaultEncoding,
|
||||||
validateArrayBufferView,
|
getArrayBufferView,
|
||||||
} = require('internal/crypto/util');
|
} = require('internal/crypto/util');
|
||||||
|
|
||||||
function pbkdf2(password, salt, iterations, keylen, digest, callback) {
|
function pbkdf2(password, salt, iterations, keylen, digest, callback) {
|
||||||
@ -64,8 +64,8 @@ function check(password, salt, iterations, keylen, digest) {
|
|||||||
digest = defaultDigest();
|
digest = defaultDigest();
|
||||||
}
|
}
|
||||||
|
|
||||||
password = validateArrayBufferView(password, 'password');
|
password = getArrayBufferView(password, 'password');
|
||||||
salt = validateArrayBufferView(salt, 'salt');
|
salt = getArrayBufferView(salt, 'salt');
|
||||||
validateUint32(iterations, 'iterations', 0);
|
validateUint32(iterations, 'iterations', 0);
|
||||||
validateUint32(keylen, 'keylen', 0);
|
validateUint32(keylen, 'keylen', 0);
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ const {
|
|||||||
} = require('internal/errors').codes;
|
} = require('internal/errors').codes;
|
||||||
const {
|
const {
|
||||||
getDefaultEncoding,
|
getDefaultEncoding,
|
||||||
validateArrayBufferView,
|
getArrayBufferView,
|
||||||
} = require('internal/crypto/util');
|
} = require('internal/crypto/util');
|
||||||
|
|
||||||
const defaults = {
|
const defaults = {
|
||||||
@ -72,8 +72,8 @@ function check(password, salt, keylen, options) {
|
|||||||
if (_scrypt === undefined)
|
if (_scrypt === undefined)
|
||||||
throw new ERR_CRYPTO_SCRYPT_NOT_SUPPORTED();
|
throw new ERR_CRYPTO_SCRYPT_NOT_SUPPORTED();
|
||||||
|
|
||||||
password = validateArrayBufferView(password, 'password');
|
password = getArrayBufferView(password, 'password');
|
||||||
salt = validateArrayBufferView(salt, 'salt');
|
salt = getArrayBufferView(salt, 'salt');
|
||||||
validateUint32(keylen, 'keylen');
|
validateUint32(keylen, 'keylen');
|
||||||
|
|
||||||
let { N, r, p, maxmem } = defaults;
|
let { N, r, p, maxmem } = defaults;
|
||||||
|
@ -17,8 +17,7 @@ const {
|
|||||||
const {
|
const {
|
||||||
getDefaultEncoding,
|
getDefaultEncoding,
|
||||||
kHandle,
|
kHandle,
|
||||||
toBuf,
|
getArrayBufferView,
|
||||||
validateArrayBufferView,
|
|
||||||
} = require('internal/crypto/util');
|
} = require('internal/crypto/util');
|
||||||
const {
|
const {
|
||||||
preparePrivateKey,
|
preparePrivateKey,
|
||||||
@ -47,8 +46,7 @@ Sign.prototype._write = function _write(chunk, encoding, callback) {
|
|||||||
|
|
||||||
Sign.prototype.update = function update(data, encoding) {
|
Sign.prototype.update = function update(data, encoding) {
|
||||||
encoding = encoding || getDefaultEncoding();
|
encoding = encoding || getDefaultEncoding();
|
||||||
data = validateArrayBufferView(toBuf(data, encoding),
|
data = getArrayBufferView(data, 'data', encoding);
|
||||||
'data');
|
|
||||||
this[kHandle].update(data);
|
this[kHandle].update(data);
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
@ -154,8 +152,7 @@ Verify.prototype.verify = function verify(options, signature, sigEncoding) {
|
|||||||
|
|
||||||
const pssSaltLength = getSaltLength(options);
|
const pssSaltLength = getSaltLength(options);
|
||||||
|
|
||||||
signature = validateArrayBufferView(toBuf(signature, sigEncoding),
|
signature = getArrayBufferView(signature, 'signature', sigEncoding);
|
||||||
'signature');
|
|
||||||
|
|
||||||
return this[kHandle].verify(data, format, type, passphrase, signature,
|
return this[kHandle].verify(data, format, type, passphrase, signature,
|
||||||
rsaPadding, pssSaltLength);
|
rsaPadding, pssSaltLength);
|
||||||
|
@ -13,10 +13,13 @@ const {
|
|||||||
} = internalBinding('constants').crypto;
|
} = internalBinding('constants').crypto;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
hideStackFrames,
|
||||||
|
codes: {
|
||||||
ERR_CRYPTO_ENGINE_UNKNOWN,
|
ERR_CRYPTO_ENGINE_UNKNOWN,
|
||||||
ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH,
|
ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH,
|
||||||
ERR_INVALID_ARG_TYPE,
|
ERR_INVALID_ARG_TYPE,
|
||||||
} = require('internal/errors').codes;
|
}
|
||||||
|
} = require('internal/errors');
|
||||||
const { validateString } = require('internal/validators');
|
const { validateString } = require('internal/validators');
|
||||||
const { Buffer } = require('buffer');
|
const { Buffer } = require('buffer');
|
||||||
const {
|
const {
|
||||||
@ -84,8 +87,12 @@ function timingSafeEqual(buf1, buf2) {
|
|||||||
return _timingSafeEqual(buf1, buf2);
|
return _timingSafeEqual(buf1, buf2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateArrayBufferView(buffer, name) {
|
const getArrayBufferView = hideStackFrames((buffer, name, encoding) => {
|
||||||
buffer = toBuf(buffer);
|
if (typeof buffer === 'string') {
|
||||||
|
if (encoding === 'buffer')
|
||||||
|
encoding = 'utf8';
|
||||||
|
return Buffer.from(buffer, encoding);
|
||||||
|
}
|
||||||
if (!isArrayBufferView(buffer)) {
|
if (!isArrayBufferView(buffer)) {
|
||||||
throw new ERR_INVALID_ARG_TYPE(
|
throw new ERR_INVALID_ARG_TYPE(
|
||||||
name,
|
name,
|
||||||
@ -94,10 +101,10 @@ function validateArrayBufferView(buffer, name) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
});
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
validateArrayBufferView,
|
getArrayBufferView,
|
||||||
getCiphers,
|
getCiphers,
|
||||||
getCurves,
|
getCurves,
|
||||||
getDefaultEncoding,
|
getDefaultEncoding,
|
||||||
|
@ -132,9 +132,6 @@ function validateSignalName(signal, name = 'signal') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(BridgeAR): We have multiple validation functions that call
|
|
||||||
// `require('internal/utils').toBuf()` before validating for array buffer views.
|
|
||||||
// Those should likely also be consolidated in here.
|
|
||||||
const validateBuffer = hideStackFrames((buffer, name = 'buffer') => {
|
const validateBuffer = hideStackFrames((buffer, name = 'buffer') => {
|
||||||
if (!isArrayBufferView(buffer)) {
|
if (!isArrayBufferView(buffer)) {
|
||||||
throw new ERR_INVALID_ARG_TYPE(name,
|
throw new ERR_INVALID_ARG_TYPE(name,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user