crypto: hide native handles from JS modules
PR-URL: https://github.com/nodejs/node/pull/22747 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
parent
2c43da8347
commit
0ade10df79
@ -2184,6 +2184,22 @@ The [Legacy URL API][] is deprecated. This includes [`url.format()`][],
|
||||
[`url.parse()`][], [`url.resolve()`][], and the [legacy `urlObject`][]. Please
|
||||
use the [WHATWG URL API][] instead.
|
||||
|
||||
<a id="DEP00XX"></a>
|
||||
### DEP00XX: Native crypto handles
|
||||
<!-- YAML
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/22747
|
||||
description: Runtime deprecation.
|
||||
-->
|
||||
|
||||
Type: Runtime
|
||||
|
||||
Previous versions of Node.js exposed handles to internal native objects through
|
||||
the `_handle` property of the `Cipher`, `Decipher`, `DiffieHellman`,
|
||||
`DiffieHellmanGroup`, `ECDH`, `Hash`, `Hmac`, `Sign`, and `Verify` classes.
|
||||
Using the `_handle` property to access the native object is deprecated because
|
||||
improper use of the native object can lead to crashing the application.
|
||||
|
||||
[`--pending-deprecation`]: cli.html#cli_pending_deprecation
|
||||
[`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size
|
||||
|
@ -14,6 +14,8 @@ const { validateString } = require('internal/validators');
|
||||
|
||||
const {
|
||||
getDefaultEncoding,
|
||||
kHandle,
|
||||
legacyNativeHandle,
|
||||
toBuf
|
||||
} = require('internal/crypto/util');
|
||||
|
||||
@ -73,11 +75,11 @@ function getUIntOption(options, key) {
|
||||
function createCipherBase(cipher, credential, options, decipher, iv) {
|
||||
const authTagLength = getUIntOption(options, 'authTagLength');
|
||||
|
||||
this._handle = new CipherBase(decipher);
|
||||
legacyNativeHandle(this, new CipherBase(decipher));
|
||||
if (iv === undefined) {
|
||||
this._handle.init(cipher, credential, authTagLength);
|
||||
this[kHandle].init(cipher, credential, authTagLength);
|
||||
} else {
|
||||
this._handle.initiv(cipher, credential, iv, authTagLength);
|
||||
this[kHandle].initiv(cipher, credential, iv, authTagLength);
|
||||
}
|
||||
this._decoder = null;
|
||||
|
||||
@ -130,13 +132,13 @@ function Cipher(cipher, password, options) {
|
||||
inherits(Cipher, LazyTransform);
|
||||
|
||||
Cipher.prototype._transform = function _transform(chunk, encoding, callback) {
|
||||
this.push(this._handle.update(chunk, encoding));
|
||||
this.push(this[kHandle].update(chunk, encoding));
|
||||
callback();
|
||||
};
|
||||
|
||||
Cipher.prototype._flush = function _flush(callback) {
|
||||
try {
|
||||
this.push(this._handle.final());
|
||||
this.push(this[kHandle].final());
|
||||
} catch (e) {
|
||||
callback(e);
|
||||
return;
|
||||
@ -157,7 +159,7 @@ Cipher.prototype.update = function update(data, inputEncoding, outputEncoding) {
|
||||
);
|
||||
}
|
||||
|
||||
const ret = this._handle.update(data, inputEncoding);
|
||||
const ret = this[kHandle].update(data, inputEncoding);
|
||||
|
||||
if (outputEncoding && outputEncoding !== 'buffer') {
|
||||
this._decoder = getDecoder(this._decoder, outputEncoding);
|
||||
@ -170,7 +172,7 @@ Cipher.prototype.update = function update(data, inputEncoding, outputEncoding) {
|
||||
|
||||
Cipher.prototype.final = function final(outputEncoding) {
|
||||
outputEncoding = outputEncoding || getDefaultEncoding();
|
||||
const ret = this._handle.final();
|
||||
const ret = this[kHandle].final();
|
||||
|
||||
if (outputEncoding && outputEncoding !== 'buffer') {
|
||||
this._decoder = getDecoder(this._decoder, outputEncoding);
|
||||
@ -182,13 +184,13 @@ Cipher.prototype.final = function final(outputEncoding) {
|
||||
|
||||
|
||||
Cipher.prototype.setAutoPadding = function setAutoPadding(ap) {
|
||||
if (!this._handle.setAutoPadding(!!ap))
|
||||
if (!this[kHandle].setAutoPadding(!!ap))
|
||||
throw new ERR_CRYPTO_INVALID_STATE('setAutoPadding');
|
||||
return this;
|
||||
};
|
||||
|
||||
Cipher.prototype.getAuthTag = function getAuthTag() {
|
||||
const ret = this._handle.getAuthTag();
|
||||
const ret = this[kHandle].getAuthTag();
|
||||
if (ret === undefined)
|
||||
throw new ERR_CRYPTO_INVALID_STATE('getAuthTag');
|
||||
return ret;
|
||||
@ -201,7 +203,7 @@ function setAuthTag(tagbuf) {
|
||||
['Buffer', 'TypedArray', 'DataView'],
|
||||
tagbuf);
|
||||
}
|
||||
if (!this._handle.setAuthTag(tagbuf))
|
||||
if (!this[kHandle].setAuthTag(tagbuf))
|
||||
throw new ERR_CRYPTO_INVALID_STATE('setAuthTag');
|
||||
return this;
|
||||
}
|
||||
@ -221,7 +223,7 @@ Cipher.prototype.setAAD = function setAAD(aadbuf, options) {
|
||||
}
|
||||
|
||||
const plaintextLength = getUIntOption(options, 'plaintextLength');
|
||||
if (!this._handle.setAAD(aadbuf, plaintextLength))
|
||||
if (!this[kHandle].setAAD(aadbuf, plaintextLength))
|
||||
throw new ERR_CRYPTO_INVALID_STATE('setAAD');
|
||||
return this;
|
||||
};
|
||||
|
@ -10,6 +10,8 @@ const { validateString } = require('internal/validators');
|
||||
const { isArrayBufferView } = require('internal/util/types');
|
||||
const {
|
||||
getDefaultEncoding,
|
||||
kHandle,
|
||||
legacyNativeHandle,
|
||||
toBuf
|
||||
} = require('internal/crypto/util');
|
||||
const {
|
||||
@ -59,10 +61,10 @@ function DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) {
|
||||
else if (typeof generator !== 'number')
|
||||
generator = toBuf(generator, genEncoding);
|
||||
|
||||
this._handle = new _DiffieHellman(sizeOrKey, generator);
|
||||
legacyNativeHandle(this, new _DiffieHellman(sizeOrKey, generator));
|
||||
Object.defineProperty(this, 'verifyError', {
|
||||
enumerable: true,
|
||||
value: this._handle.verifyError,
|
||||
value: this[kHandle].verifyError,
|
||||
writable: false
|
||||
});
|
||||
}
|
||||
@ -71,10 +73,10 @@ function DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) {
|
||||
function DiffieHellmanGroup(name) {
|
||||
if (!(this instanceof DiffieHellmanGroup))
|
||||
return new DiffieHellmanGroup(name);
|
||||
this._handle = new _DiffieHellmanGroup(name);
|
||||
legacyNativeHandle(this, new _DiffieHellmanGroup(name));
|
||||
Object.defineProperty(this, 'verifyError', {
|
||||
enumerable: true,
|
||||
value: this._handle.verifyError,
|
||||
value: this[kHandle].verifyError,
|
||||
writable: false
|
||||
});
|
||||
}
|
||||
@ -85,7 +87,7 @@ DiffieHellmanGroup.prototype.generateKeys =
|
||||
dhGenerateKeys;
|
||||
|
||||
function dhGenerateKeys(encoding) {
|
||||
const keys = this._handle.generateKeys();
|
||||
const keys = this[kHandle].generateKeys();
|
||||
encoding = encoding || getDefaultEncoding();
|
||||
return encode(keys, encoding);
|
||||
}
|
||||
@ -99,7 +101,7 @@ function dhComputeSecret(key, inEnc, outEnc) {
|
||||
const encoding = getDefaultEncoding();
|
||||
inEnc = inEnc || encoding;
|
||||
outEnc = outEnc || encoding;
|
||||
const ret = this._handle.computeSecret(toBuf(key, inEnc));
|
||||
const ret = this[kHandle].computeSecret(toBuf(key, inEnc));
|
||||
if (typeof ret === 'string')
|
||||
throw new ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY();
|
||||
return encode(ret, outEnc);
|
||||
@ -111,7 +113,7 @@ DiffieHellmanGroup.prototype.getPrime =
|
||||
dhGetPrime;
|
||||
|
||||
function dhGetPrime(encoding) {
|
||||
const prime = this._handle.getPrime();
|
||||
const prime = this[kHandle].getPrime();
|
||||
encoding = encoding || getDefaultEncoding();
|
||||
return encode(prime, encoding);
|
||||
}
|
||||
@ -122,7 +124,7 @@ DiffieHellmanGroup.prototype.getGenerator =
|
||||
dhGetGenerator;
|
||||
|
||||
function dhGetGenerator(encoding) {
|
||||
const generator = this._handle.getGenerator();
|
||||
const generator = this[kHandle].getGenerator();
|
||||
encoding = encoding || getDefaultEncoding();
|
||||
return encode(generator, encoding);
|
||||
}
|
||||
@ -133,7 +135,7 @@ DiffieHellmanGroup.prototype.getPublicKey =
|
||||
dhGetPublicKey;
|
||||
|
||||
function dhGetPublicKey(encoding) {
|
||||
const key = this._handle.getPublicKey();
|
||||
const key = this[kHandle].getPublicKey();
|
||||
encoding = encoding || getDefaultEncoding();
|
||||
return encode(key, encoding);
|
||||
}
|
||||
@ -144,7 +146,7 @@ DiffieHellmanGroup.prototype.getPrivateKey =
|
||||
dhGetPrivateKey;
|
||||
|
||||
function dhGetPrivateKey(encoding) {
|
||||
const key = this._handle.getPrivateKey();
|
||||
const key = this[kHandle].getPrivateKey();
|
||||
encoding = encoding || getDefaultEncoding();
|
||||
return encode(key, encoding);
|
||||
}
|
||||
@ -152,14 +154,14 @@ function dhGetPrivateKey(encoding) {
|
||||
|
||||
DiffieHellman.prototype.setPublicKey = function setPublicKey(key, encoding) {
|
||||
encoding = encoding || getDefaultEncoding();
|
||||
this._handle.setPublicKey(toBuf(key, encoding));
|
||||
this[kHandle].setPublicKey(toBuf(key, encoding));
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
DiffieHellman.prototype.setPrivateKey = function setPrivateKey(key, encoding) {
|
||||
encoding = encoding || getDefaultEncoding();
|
||||
this._handle.setPrivateKey(toBuf(key, encoding));
|
||||
this[kHandle].setPrivateKey(toBuf(key, encoding));
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -169,7 +171,7 @@ function ECDH(curve) {
|
||||
return new ECDH(curve);
|
||||
|
||||
validateString(curve, 'curve');
|
||||
this._handle = new _ECDH(curve);
|
||||
legacyNativeHandle(this, new _ECDH(curve));
|
||||
}
|
||||
|
||||
ECDH.prototype.computeSecret = DiffieHellman.prototype.computeSecret;
|
||||
@ -178,14 +180,14 @@ ECDH.prototype.setPublicKey = DiffieHellman.prototype.setPublicKey;
|
||||
ECDH.prototype.getPrivateKey = DiffieHellman.prototype.getPrivateKey;
|
||||
|
||||
ECDH.prototype.generateKeys = function generateKeys(encoding, format) {
|
||||
this._handle.generateKeys();
|
||||
this[kHandle].generateKeys();
|
||||
|
||||
return this.getPublicKey(encoding, format);
|
||||
};
|
||||
|
||||
ECDH.prototype.getPublicKey = function getPublicKey(encoding, format) {
|
||||
const f = getFormat(format);
|
||||
const key = this._handle.getPublicKey(f);
|
||||
const key = this[kHandle].getPublicKey(f);
|
||||
encoding = encoding || getDefaultEncoding();
|
||||
return encode(key, encoding);
|
||||
};
|
||||
|
@ -7,6 +7,8 @@ const {
|
||||
|
||||
const {
|
||||
getDefaultEncoding,
|
||||
kHandle,
|
||||
legacyNativeHandle,
|
||||
toBuf
|
||||
} = require('internal/crypto/util');
|
||||
|
||||
@ -30,7 +32,7 @@ function Hash(algorithm, options) {
|
||||
if (!(this instanceof Hash))
|
||||
return new Hash(algorithm, options);
|
||||
validateString(algorithm, 'algorithm');
|
||||
this._handle = new _Hash(algorithm);
|
||||
legacyNativeHandle(this, new _Hash(algorithm));
|
||||
this[kState] = {
|
||||
[kFinalized]: false
|
||||
};
|
||||
@ -40,12 +42,12 @@ function Hash(algorithm, options) {
|
||||
inherits(Hash, LazyTransform);
|
||||
|
||||
Hash.prototype._transform = function _transform(chunk, encoding, callback) {
|
||||
this._handle.update(chunk, encoding);
|
||||
this[kHandle].update(chunk, encoding);
|
||||
callback();
|
||||
};
|
||||
|
||||
Hash.prototype._flush = function _flush(callback) {
|
||||
this.push(this._handle.digest());
|
||||
this.push(this[kHandle].digest());
|
||||
callback();
|
||||
};
|
||||
|
||||
@ -59,7 +61,7 @@ Hash.prototype.update = function update(data, encoding) {
|
||||
['string', 'TypedArray', 'DataView'], data);
|
||||
}
|
||||
|
||||
if (!this._handle.update(data, encoding || getDefaultEncoding()))
|
||||
if (!this[kHandle].update(data, encoding || getDefaultEncoding()))
|
||||
throw new ERR_CRYPTO_HASH_UPDATE_FAILED();
|
||||
return this;
|
||||
};
|
||||
@ -74,7 +76,7 @@ Hash.prototype.digest = function digest(outputEncoding) {
|
||||
throw new ERR_CRYPTO_HASH_DIGEST_NO_UTF16();
|
||||
|
||||
// Explicit conversion for backward compatibility.
|
||||
const ret = this._handle.digest(`${outputEncoding}`);
|
||||
const ret = this[kHandle].digest(`${outputEncoding}`);
|
||||
state[kFinalized] = true;
|
||||
return ret;
|
||||
};
|
||||
@ -88,8 +90,8 @@ function Hmac(hmac, key, options) {
|
||||
throw new ERR_INVALID_ARG_TYPE('key',
|
||||
['string', 'TypedArray', 'DataView'], key);
|
||||
}
|
||||
this._handle = new _Hmac();
|
||||
this._handle.init(hmac, toBuf(key));
|
||||
legacyNativeHandle(this, new _Hmac());
|
||||
this[kHandle].init(hmac, toBuf(key));
|
||||
this[kState] = {
|
||||
[kFinalized]: false
|
||||
};
|
||||
@ -112,7 +114,7 @@ Hmac.prototype.digest = function digest(outputEncoding) {
|
||||
}
|
||||
|
||||
// Explicit conversion for backward compatibility.
|
||||
const ret = this._handle.digest(`${outputEncoding}`);
|
||||
const ret = this[kHandle].digest(`${outputEncoding}`);
|
||||
state[kFinalized] = true;
|
||||
return ret;
|
||||
};
|
||||
|
@ -13,6 +13,8 @@ const {
|
||||
} = process.binding('constants').crypto;
|
||||
const {
|
||||
getDefaultEncoding,
|
||||
kHandle,
|
||||
legacyNativeHandle,
|
||||
toBuf,
|
||||
validateArrayBufferView,
|
||||
} = require('internal/crypto/util');
|
||||
@ -23,8 +25,8 @@ function Sign(algorithm, options) {
|
||||
if (!(this instanceof Sign))
|
||||
return new Sign(algorithm, options);
|
||||
validateString(algorithm, 'algorithm');
|
||||
this._handle = new _Sign();
|
||||
this._handle.init(algorithm);
|
||||
legacyNativeHandle(this, new _Sign());
|
||||
this[kHandle].init(algorithm);
|
||||
|
||||
Writable.call(this, options);
|
||||
}
|
||||
@ -40,7 +42,7 @@ Sign.prototype.update = function update(data, encoding) {
|
||||
encoding = encoding || getDefaultEncoding();
|
||||
data = validateArrayBufferView(toBuf(data, encoding),
|
||||
'data');
|
||||
this._handle.update(data);
|
||||
this[kHandle].update(data);
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -78,7 +80,7 @@ Sign.prototype.sign = function sign(options, encoding) {
|
||||
|
||||
key = validateArrayBufferView(key, 'key');
|
||||
|
||||
var ret = this._handle.sign(key, passphrase, rsaPadding, pssSaltLength);
|
||||
var ret = this[kHandle].sign(key, passphrase, rsaPadding, pssSaltLength);
|
||||
|
||||
encoding = encoding || getDefaultEncoding();
|
||||
if (encoding && encoding !== 'buffer')
|
||||
@ -92,8 +94,8 @@ function Verify(algorithm, options) {
|
||||
if (!(this instanceof Verify))
|
||||
return new Verify(algorithm, options);
|
||||
validateString(algorithm, 'algorithm');
|
||||
this._handle = new _Verify();
|
||||
this._handle.init(algorithm);
|
||||
legacyNativeHandle(this, new _Verify());
|
||||
this[kHandle].init(algorithm);
|
||||
|
||||
Writable.call(this, options);
|
||||
}
|
||||
@ -117,7 +119,7 @@ Verify.prototype.verify = function verify(options, signature, sigEncoding) {
|
||||
signature = validateArrayBufferView(toBuf(signature, sigEncoding),
|
||||
'signature');
|
||||
|
||||
return this._handle.verify(key, signature, rsaPadding, pssSaltLength);
|
||||
return this[kHandle].verify(key, signature, rsaPadding, pssSaltLength);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
@ -22,12 +22,28 @@ const { validateString } = require('internal/validators');
|
||||
const { Buffer } = require('buffer');
|
||||
const {
|
||||
cachedResult,
|
||||
deprecate,
|
||||
filterDuplicateStrings
|
||||
} = require('internal/util');
|
||||
const {
|
||||
isArrayBufferView
|
||||
} = require('internal/util/types');
|
||||
|
||||
const kHandle = Symbol('kHandle');
|
||||
|
||||
function legacyNativeHandle(obj, handle) {
|
||||
obj[kHandle] = handle;
|
||||
Object.defineProperty(obj, '_handle', {
|
||||
get: deprecate(() => handle,
|
||||
`${obj.constructor.name}._handle is deprecated. Use the ` +
|
||||
'public API instead.', 'DEP00XX'),
|
||||
set: deprecate((h) => obj[kHandle] = handle = h,
|
||||
`${obj.constructor.name}._handle is deprecated. Use the ` +
|
||||
'public API instead.', 'DEP00XX'),
|
||||
enumerable: false
|
||||
});
|
||||
}
|
||||
|
||||
var defaultEncoding = 'buffer';
|
||||
|
||||
function setDefaultEncoding(val) {
|
||||
@ -101,6 +117,8 @@ module.exports = {
|
||||
getCurves,
|
||||
getDefaultEncoding,
|
||||
getHashes,
|
||||
kHandle,
|
||||
legacyNativeHandle,
|
||||
setDefaultEncoding,
|
||||
setEngine,
|
||||
timingSafeEqual,
|
||||
|
Loading…
x
Reference in New Issue
Block a user