Files
node/lib/crypto.js
Tobias Nießen eaa0542eff crypto: remove unused C++ parameter in sign/verify
Removes code in node_crypto.cc in Sign::SignFinal and
Verify::VerifyFinal which allowed to convert between buffers and
strings based on given encodings. The code is unused as crypto.js
only passes in and expects buffers and does the conversion itself.
The encoding parameter was removed from both methods.

PR-URL: https://github.com/nodejs/node/pull/12397
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2017-04-18 11:37:34 -07:00

810 lines
23 KiB
JavaScript

// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// Note: In 0.8 and before, crypto functions all defaulted to using
// binary-encoded strings rather than buffers.
'use strict';
const internalUtil = require('internal/util');
internalUtil.assertCrypto();
exports.DEFAULT_ENCODING = 'buffer';
const constants = process.binding('constants').crypto;
const binding = process.binding('crypto');
const randomBytes = binding.randomBytes;
const getCiphers = binding.getCiphers;
const getHashes = binding.getHashes;
const getCurves = binding.getCurves;
const getFipsCrypto = binding.getFipsCrypto;
const setFipsCrypto = binding.setFipsCrypto;
const timingSafeEqual = binding.timingSafeEqual;
const Buffer = require('buffer').Buffer;
const kBufferMaxLength = require('buffer').kMaxLength;
const stream = require('stream');
const util = require('util');
const { isUint8Array } = process.binding('util');
const LazyTransform = require('internal/streams/lazy_transform');
const DH_GENERATOR = 2;
Object.defineProperty(exports, 'constants', {
configurable: false,
enumerable: true,
value: constants
});
// This is here because many functions accepted binary strings without
// any explicit encoding in older versions of node, and we don't want
// to break them unnecessarily.
function toBuf(str, encoding) {
if (typeof str === 'string') {
if (encoding === 'buffer' || !encoding)
encoding = 'utf8';
return Buffer.from(str, encoding);
}
return str;
}
exports._toBuf = toBuf;
const assert = require('assert');
const StringDecoder = require('string_decoder').StringDecoder;
exports.createHash = exports.Hash = Hash;
function Hash(algorithm, options) {
if (!(this instanceof Hash))
return new Hash(algorithm, options);
this._handle = new binding.Hash(algorithm);
LazyTransform.call(this, options);
}
util.inherits(Hash, LazyTransform);
Hash.prototype._transform = function _transform(chunk, encoding, callback) {
this._handle.update(chunk, encoding);
callback();
};
Hash.prototype._flush = function _flush(callback) {
this.push(this._handle.digest());
callback();
};
Hash.prototype.update = function update(data, encoding) {
encoding = encoding || exports.DEFAULT_ENCODING;
this._handle.update(data, encoding);
return this;
};
Hash.prototype.digest = function digest(outputEncoding) {
outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
// Explicit conversion for backward compatibility.
return this._handle.digest(`${outputEncoding}`);
};
exports.createHmac = exports.Hmac = Hmac;
function Hmac(hmac, key, options) {
if (!(this instanceof Hmac))
return new Hmac(hmac, key, options);
this._handle = new binding.Hmac();
this._handle.init(hmac, toBuf(key));
LazyTransform.call(this, options);
}
util.inherits(Hmac, LazyTransform);
Hmac.prototype.update = Hash.prototype.update;
Hmac.prototype.digest = Hash.prototype.digest;
Hmac.prototype._flush = Hash.prototype._flush;
Hmac.prototype._transform = Hash.prototype._transform;
function getDecoder(decoder, encoding) {
encoding = internalUtil.normalizeEncoding(encoding);
decoder = decoder || new StringDecoder(encoding);
assert(decoder.encoding === encoding, 'Cannot change encoding');
return decoder;
}
exports.createCipher = exports.Cipher = Cipher;
function Cipher(cipher, password, options) {
if (!(this instanceof Cipher))
return new Cipher(cipher, password, options);
this._handle = new binding.CipherBase(true);
this._handle.init(cipher, toBuf(password));
this._decoder = null;
LazyTransform.call(this, options);
}
util.inherits(Cipher, LazyTransform);
Cipher.prototype._transform = function _transform(chunk, encoding, callback) {
this.push(this._handle.update(chunk, encoding));
callback();
};
Cipher.prototype._flush = function _flush(callback) {
try {
this.push(this._handle.final());
} catch (e) {
callback(e);
return;
}
callback();
};
Cipher.prototype.update = function update(data, inputEncoding, outputEncoding) {
inputEncoding = inputEncoding || exports.DEFAULT_ENCODING;
outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
var ret = this._handle.update(data, inputEncoding);
if (outputEncoding && outputEncoding !== 'buffer') {
this._decoder = getDecoder(this._decoder, outputEncoding);
ret = this._decoder.write(ret);
}
return ret;
};
Cipher.prototype.final = function final(outputEncoding) {
outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
var ret = this._handle.final();
if (outputEncoding && outputEncoding !== 'buffer') {
this._decoder = getDecoder(this._decoder, outputEncoding);
ret = this._decoder.end(ret);
}
return ret;
};
Cipher.prototype.setAutoPadding = function setAutoPadding(ap) {
this._handle.setAutoPadding(ap);
return this;
};
Cipher.prototype.getAuthTag = function getAuthTag() {
return this._handle.getAuthTag();
};
Cipher.prototype.setAuthTag = function setAuthTag(tagbuf) {
this._handle.setAuthTag(tagbuf);
return this;
};
Cipher.prototype.setAAD = function setAAD(aadbuf) {
this._handle.setAAD(aadbuf);
return this;
};
exports.createCipheriv = exports.Cipheriv = Cipheriv;
function Cipheriv(cipher, key, iv, options) {
if (!(this instanceof Cipheriv))
return new Cipheriv(cipher, key, iv, options);
this._handle = new binding.CipherBase(true);
this._handle.initiv(cipher, toBuf(key), toBuf(iv));
this._decoder = null;
LazyTransform.call(this, options);
}
util.inherits(Cipheriv, LazyTransform);
Cipheriv.prototype._transform = Cipher.prototype._transform;
Cipheriv.prototype._flush = Cipher.prototype._flush;
Cipheriv.prototype.update = Cipher.prototype.update;
Cipheriv.prototype.final = Cipher.prototype.final;
Cipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
Cipheriv.prototype.getAuthTag = Cipher.prototype.getAuthTag;
Cipheriv.prototype.setAuthTag = Cipher.prototype.setAuthTag;
Cipheriv.prototype.setAAD = Cipher.prototype.setAAD;
exports.createDecipher = exports.Decipher = Decipher;
function Decipher(cipher, password, options) {
if (!(this instanceof Decipher))
return new Decipher(cipher, password, options);
this._handle = new binding.CipherBase(false);
this._handle.init(cipher, toBuf(password));
this._decoder = null;
LazyTransform.call(this, options);
}
util.inherits(Decipher, LazyTransform);
Decipher.prototype._transform = Cipher.prototype._transform;
Decipher.prototype._flush = Cipher.prototype._flush;
Decipher.prototype.update = Cipher.prototype.update;
Decipher.prototype.final = Cipher.prototype.final;
Decipher.prototype.finaltol = Cipher.prototype.final;
Decipher.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
Decipher.prototype.getAuthTag = Cipher.prototype.getAuthTag;
Decipher.prototype.setAuthTag = Cipher.prototype.setAuthTag;
Decipher.prototype.setAAD = Cipher.prototype.setAAD;
exports.createDecipheriv = exports.Decipheriv = Decipheriv;
function Decipheriv(cipher, key, iv, options) {
if (!(this instanceof Decipheriv))
return new Decipheriv(cipher, key, iv, options);
this._handle = new binding.CipherBase(false);
this._handle.initiv(cipher, toBuf(key), toBuf(iv));
this._decoder = null;
LazyTransform.call(this, options);
}
util.inherits(Decipheriv, LazyTransform);
Decipheriv.prototype._transform = Cipher.prototype._transform;
Decipheriv.prototype._flush = Cipher.prototype._flush;
Decipheriv.prototype.update = Cipher.prototype.update;
Decipheriv.prototype.final = Cipher.prototype.final;
Decipheriv.prototype.finaltol = Cipher.prototype.final;
Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
Decipheriv.prototype.getAuthTag = Cipher.prototype.getAuthTag;
Decipheriv.prototype.setAuthTag = Cipher.prototype.setAuthTag;
Decipheriv.prototype.setAAD = Cipher.prototype.setAAD;
exports.createSign = exports.Sign = Sign;
function Sign(algorithm, options) {
if (!(this instanceof Sign))
return new Sign(algorithm, options);
this._handle = new binding.Sign();
this._handle.init(algorithm);
stream.Writable.call(this, options);
}
util.inherits(Sign, stream.Writable);
Sign.prototype._write = function _write(chunk, encoding, callback) {
this._handle.update(chunk, encoding);
callback();
};
Sign.prototype.update = Hash.prototype.update;
Sign.prototype.sign = function sign(options, encoding) {
if (!options)
throw new Error('No key provided to sign');
var key = options.key || options;
var passphrase = options.passphrase || null;
// Options specific to RSA
var rsaPadding = constants.RSA_PKCS1_PADDING;
if (options.hasOwnProperty('padding')) {
if (options.padding === options.padding >> 0) {
rsaPadding = options.padding;
} else {
throw new TypeError('padding must be an integer');
}
}
var pssSaltLength = constants.RSA_PSS_SALTLEN_AUTO;
if (options.hasOwnProperty('saltLength')) {
if (options.saltLength === options.saltLength >> 0) {
pssSaltLength = options.saltLength;
} else {
throw new TypeError('saltLength must be an integer');
}
}
var ret = this._handle.sign(toBuf(key), passphrase, rsaPadding,
pssSaltLength);
encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding && encoding !== 'buffer')
ret = ret.toString(encoding);
return ret;
};
exports.createVerify = exports.Verify = Verify;
function Verify(algorithm, options) {
if (!(this instanceof Verify))
return new Verify(algorithm, options);
this._handle = new binding.Verify();
this._handle.init(algorithm);
stream.Writable.call(this, options);
}
util.inherits(Verify, stream.Writable);
Verify.prototype._write = Sign.prototype._write;
Verify.prototype.update = Sign.prototype.update;
Verify.prototype.verify = function verify(options, signature, sigEncoding) {
var key = options.key || options;
sigEncoding = sigEncoding || exports.DEFAULT_ENCODING;
// Options specific to RSA
var rsaPadding = constants.RSA_PKCS1_PADDING;
if (options.hasOwnProperty('padding')) {
if (options.padding === options.padding >> 0) {
rsaPadding = options.padding;
} else {
throw new TypeError('padding must be an integer');
}
}
var pssSaltLength = constants.RSA_PSS_SALTLEN_AUTO;
if (options.hasOwnProperty('saltLength')) {
if (options.saltLength === options.saltLength >> 0) {
pssSaltLength = options.saltLength;
} else {
throw new TypeError('saltLength must be an integer');
}
}
return this._handle.verify(toBuf(key), toBuf(signature, sigEncoding),
rsaPadding, pssSaltLength);
};
function rsaPublic(method, defaultPadding) {
return function(options, buffer) {
var key = options.key || options;
var padding = options.padding || defaultPadding;
var passphrase = options.passphrase || null;
return method(toBuf(key), buffer, padding, passphrase);
};
}
function rsaPrivate(method, defaultPadding) {
return function(options, buffer) {
var key = options.key || options;
var passphrase = options.passphrase || null;
var padding = options.padding || defaultPadding;
return method(toBuf(key), buffer, padding, passphrase);
};
}
exports.publicEncrypt = rsaPublic(binding.publicEncrypt,
constants.RSA_PKCS1_OAEP_PADDING);
exports.publicDecrypt = rsaPublic(binding.publicDecrypt,
constants.RSA_PKCS1_PADDING);
exports.privateEncrypt = rsaPrivate(binding.privateEncrypt,
constants.RSA_PKCS1_PADDING);
exports.privateDecrypt = rsaPrivate(binding.privateDecrypt,
constants.RSA_PKCS1_OAEP_PADDING);
exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman;
function DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) {
if (!(this instanceof DiffieHellman))
return new DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding);
if (typeof sizeOrKey !== 'number' &&
typeof sizeOrKey !== 'string' &&
!ArrayBuffer.isView(sizeOrKey)) {
throw new TypeError('First argument should be number, string, ' +
'Buffer, TypedArray, or DataView');
}
if (keyEncoding) {
if (typeof keyEncoding !== 'string' ||
(!Buffer.isEncoding(keyEncoding) && keyEncoding !== 'buffer')) {
genEncoding = generator;
generator = keyEncoding;
keyEncoding = false;
}
}
keyEncoding = keyEncoding || exports.DEFAULT_ENCODING;
genEncoding = genEncoding || exports.DEFAULT_ENCODING;
if (typeof sizeOrKey !== 'number')
sizeOrKey = toBuf(sizeOrKey, keyEncoding);
if (!generator)
generator = DH_GENERATOR;
else if (typeof generator !== 'number')
generator = toBuf(generator, genEncoding);
this._handle = new binding.DiffieHellman(sizeOrKey, generator);
Object.defineProperty(this, 'verifyError', {
enumerable: true,
value: this._handle.verifyError,
writable: false
});
}
exports.DiffieHellmanGroup =
exports.createDiffieHellmanGroup =
exports.getDiffieHellman = DiffieHellmanGroup;
function DiffieHellmanGroup(name) {
if (!(this instanceof DiffieHellmanGroup))
return new DiffieHellmanGroup(name);
this._handle = new binding.DiffieHellmanGroup(name);
Object.defineProperty(this, 'verifyError', {
enumerable: true,
value: this._handle.verifyError,
writable: false
});
}
DiffieHellmanGroup.prototype.generateKeys =
DiffieHellman.prototype.generateKeys =
dhGenerateKeys;
function dhGenerateKeys(encoding) {
var keys = this._handle.generateKeys();
encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding && encoding !== 'buffer')
keys = keys.toString(encoding);
return keys;
}
DiffieHellmanGroup.prototype.computeSecret =
DiffieHellman.prototype.computeSecret =
dhComputeSecret;
function dhComputeSecret(key, inEnc, outEnc) {
inEnc = inEnc || exports.DEFAULT_ENCODING;
outEnc = outEnc || exports.DEFAULT_ENCODING;
var ret = this._handle.computeSecret(toBuf(key, inEnc));
if (outEnc && outEnc !== 'buffer')
ret = ret.toString(outEnc);
return ret;
}
DiffieHellmanGroup.prototype.getPrime =
DiffieHellman.prototype.getPrime =
dhGetPrime;
function dhGetPrime(encoding) {
var prime = this._handle.getPrime();
encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding && encoding !== 'buffer')
prime = prime.toString(encoding);
return prime;
}
DiffieHellmanGroup.prototype.getGenerator =
DiffieHellman.prototype.getGenerator =
dhGetGenerator;
function dhGetGenerator(encoding) {
var generator = this._handle.getGenerator();
encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding && encoding !== 'buffer')
generator = generator.toString(encoding);
return generator;
}
DiffieHellmanGroup.prototype.getPublicKey =
DiffieHellman.prototype.getPublicKey =
dhGetPublicKey;
function dhGetPublicKey(encoding) {
var key = this._handle.getPublicKey();
encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding && encoding !== 'buffer')
key = key.toString(encoding);
return key;
}
DiffieHellmanGroup.prototype.getPrivateKey =
DiffieHellman.prototype.getPrivateKey =
dhGetPrivateKey;
function dhGetPrivateKey(encoding) {
var key = this._handle.getPrivateKey();
encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding && encoding !== 'buffer')
key = key.toString(encoding);
return key;
}
DiffieHellman.prototype.setPublicKey = function setPublicKey(key, encoding) {
encoding = encoding || exports.DEFAULT_ENCODING;
this._handle.setPublicKey(toBuf(key, encoding));
return this;
};
DiffieHellman.prototype.setPrivateKey = function setPrivateKey(key, encoding) {
encoding = encoding || exports.DEFAULT_ENCODING;
this._handle.setPrivateKey(toBuf(key, encoding));
return this;
};
function ECDH(curve) {
if (typeof curve !== 'string')
throw new TypeError('"curve" argument should be a string');
this._handle = new binding.ECDH(curve);
}
exports.createECDH = function createECDH(curve) {
return new ECDH(curve);
};
ECDH.prototype.computeSecret = DiffieHellman.prototype.computeSecret;
ECDH.prototype.setPrivateKey = DiffieHellman.prototype.setPrivateKey;
ECDH.prototype.setPublicKey = DiffieHellman.prototype.setPublicKey;
ECDH.prototype.getPrivateKey = DiffieHellman.prototype.getPrivateKey;
ECDH.prototype.generateKeys = function generateKeys(encoding, format) {
this._handle.generateKeys();
return this.getPublicKey(encoding, format);
};
ECDH.prototype.getPublicKey = function getPublicKey(encoding, format) {
var f;
if (format) {
if (typeof format === 'number')
f = format;
if (format === 'compressed')
f = constants.POINT_CONVERSION_COMPRESSED;
else if (format === 'hybrid')
f = constants.POINT_CONVERSION_HYBRID;
// Default
else if (format === 'uncompressed')
f = constants.POINT_CONVERSION_UNCOMPRESSED;
else
throw new TypeError('Bad format: ' + format);
} else {
f = constants.POINT_CONVERSION_UNCOMPRESSED;
}
var key = this._handle.getPublicKey(f);
encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding && encoding !== 'buffer')
key = key.toString(encoding);
return key;
};
exports.pbkdf2 = function(password,
salt,
iterations,
keylen,
digest,
callback) {
if (typeof digest === 'function') {
callback = digest;
digest = undefined;
}
if (typeof callback !== 'function')
throw new Error('No callback provided to pbkdf2');
return pbkdf2(password, salt, iterations, keylen, digest, callback);
};
exports.pbkdf2Sync = function(password, salt, iterations, keylen, digest) {
return pbkdf2(password, salt, iterations, keylen, digest);
};
function pbkdf2(password, salt, iterations, keylen, digest, callback) {
if (digest === undefined) {
throw new TypeError(
'The "digest" argument is required and must not be undefined');
}
password = toBuf(password);
salt = toBuf(salt);
if (exports.DEFAULT_ENCODING === 'buffer')
return binding.PBKDF2(password, salt, iterations, keylen, digest, callback);
// at this point, we need to handle encodings.
var encoding = exports.DEFAULT_ENCODING;
if (callback) {
var next = function(er, ret) {
if (ret)
ret = ret.toString(encoding);
callback(er, ret);
};
binding.PBKDF2(password, salt, iterations, keylen, digest, next);
} else {
var ret = binding.PBKDF2(password, salt, iterations, keylen, digest);
return ret.toString(encoding);
}
}
exports.Certificate = Certificate;
function Certificate() {
if (!(this instanceof Certificate))
return new Certificate();
}
Certificate.prototype.verifySpkac = function verifySpkac(object) {
return binding.certVerifySpkac(object);
};
Certificate.prototype.exportPublicKey =
function exportPublicKey(object, encoding) {
return binding.certExportPublicKey(toBuf(object, encoding));
};
Certificate.prototype.exportChallenge =
function exportChallenge(object, encoding) {
return binding.certExportChallenge(toBuf(object, encoding));
};
exports.setEngine = function setEngine(id, flags) {
if (typeof id !== 'string')
throw new TypeError('"id" argument should be a string');
if (flags && typeof flags !== 'number')
throw new TypeError('"flags" argument should be a number, if present');
flags = flags >>> 0;
// Use provided engine for everything by default
if (flags === 0)
flags = constants.ENGINE_METHOD_ALL;
return binding.setEngine(id, flags);
};
const kMaxUint32 = Math.pow(2, 32) - 1;
function randomFillSync(buf, offset = 0, size) {
if (!isUint8Array(buf)) {
throw new TypeError('"buf" argument must be a Buffer or Uint8Array');
}
assertOffset(offset, buf.length);
if (size === undefined) size = buf.length - offset;
assertSize(size, offset, buf.length);
return binding.randomFill(buf, offset, size);
}
exports.randomFillSync = randomFillSync;
function randomFill(buf, offset, size, cb) {
if (!isUint8Array(buf)) {
throw new TypeError('"buf" argument must be a Buffer or Uint8Array');
}
if (typeof offset === 'function') {
cb = offset;
offset = 0;
size = buf.length;
} else if (typeof size === 'function') {
cb = size;
size = buf.length - offset;
} else if (typeof cb !== 'function') {
throw new TypeError('"cb" argument must be a function');
}
assertOffset(offset, buf.length);
assertSize(size, offset, buf.length);
return binding.randomFill(buf, offset, size, cb);
}
exports.randomFill = randomFill;
function assertOffset(offset, length) {
if (typeof offset !== 'number' || offset !== offset) {
throw new TypeError('offset must be a number');
}
if (offset > kMaxUint32 || offset < 0) {
throw new TypeError('offset must be a uint32');
}
if (offset > kBufferMaxLength || offset > length) {
throw new RangeError('offset out of range');
}
}
function assertSize(size, offset, length) {
if (typeof size !== 'number' || size !== size) {
throw new TypeError('size must be a number');
}
if (size > kMaxUint32 || size < 0) {
throw new TypeError('size must be a uint32');
}
if (size + offset > length || size > kBufferMaxLength) {
throw new RangeError('buffer too small');
}
}
exports.randomBytes = exports.pseudoRandomBytes = randomBytes;
exports.rng = exports.prng = randomBytes;
exports.getCiphers = internalUtil.cachedResult(
() => internalUtil.filterDuplicateStrings(getCiphers())
);
exports.getHashes = internalUtil.cachedResult(
() => internalUtil.filterDuplicateStrings(getHashes())
);
exports.getCurves = internalUtil.cachedResult(
() => internalUtil.filterDuplicateStrings(getCurves())
);
Object.defineProperty(exports, 'fips', {
get: getFipsCrypto,
set: setFipsCrypto
});
exports.timingSafeEqual = timingSafeEqual;
// Legacy API
Object.defineProperty(exports, 'createCredentials', {
configurable: true,
enumerable: true,
get: internalUtil.deprecate(function() {
return require('tls').createSecureContext;
}, 'crypto.createCredentials is deprecated. ' +
'Use tls.createSecureContext instead.', 'DEP0010')
});
Object.defineProperty(exports, 'Credentials', {
configurable: true,
enumerable: true,
get: internalUtil.deprecate(function() {
return require('tls').SecureContext;
}, 'crypto.Credentials is deprecated. ' +
'Use tls.SecureContext instead.', 'DEP0011')
});