forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Split single monolithic file into multiple * Make Certificate methods static * Allow randomFill(Sync) to use any ArrayBufferView * Use internal/errors throughout * Improve arg validation in Hash/Hmac * Doc updates PR-URL: nodejs#15231 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Fedor Indutny <[email protected]>
Showing
25 changed files
with
1,712 additions
and
1,030 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
'use strict'; | ||
|
||
const { | ||
certExportChallenge, | ||
certExportPublicKey, | ||
certVerifySpkac | ||
} = process.binding('crypto'); | ||
|
||
const { | ||
toBuf | ||
} = require('internal/crypto/util'); | ||
|
||
function verifySpkac(object) { | ||
return certVerifySpkac(object); | ||
} | ||
|
||
function exportPublicKey(object, encoding) { | ||
return certExportPublicKey(toBuf(object, encoding)); | ||
} | ||
|
||
function exportChallenge(object, encoding) { | ||
return certExportChallenge(toBuf(object, encoding)); | ||
} | ||
|
||
// For backwards compatibility reasons, this cannot be converted into a | ||
// ES6 Class. | ||
function Certificate() { | ||
if (!(this instanceof Certificate)) | ||
return new Certificate(); | ||
} | ||
|
||
Certificate.prototype.verifySpkac = verifySpkac; | ||
Certificate.prototype.exportPublicKey = exportPublicKey; | ||
Certificate.prototype.exportChallenge = exportChallenge; | ||
|
||
Certificate.exportChallenge = exportChallenge; | ||
Certificate.exportPublicKey = exportPublicKey; | ||
Certificate.verifySpkac = verifySpkac; | ||
|
||
module.exports = Certificate; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
'use strict'; | ||
|
||
const { | ||
RSA_PKCS1_OAEP_PADDING, | ||
RSA_PKCS1_PADDING | ||
} = process.binding('constants').crypto; | ||
|
||
const { | ||
getDefaultEncoding, | ||
toBuf | ||
} = require('internal/crypto/util'); | ||
|
||
const { | ||
CipherBase, | ||
privateDecrypt: _privateDecrypt, | ||
privateEncrypt: _privateEncrypt, | ||
publicDecrypt: _publicDecrypt, | ||
publicEncrypt: _publicEncrypt | ||
} = process.binding('crypto'); | ||
|
||
const assert = require('assert'); | ||
const LazyTransform = require('internal/streams/lazy_transform'); | ||
const { StringDecoder } = require('string_decoder'); | ||
|
||
const { inherits } = require('util'); | ||
const { normalizeEncoding } = require('internal/util'); | ||
|
||
function rsaPublic(method, defaultPadding) { | ||
return function(options, buffer) { | ||
const key = options.key || options; | ||
const padding = options.padding || defaultPadding; | ||
const passphrase = options.passphrase || null; | ||
return method(toBuf(key), buffer, padding, passphrase); | ||
}; | ||
} | ||
|
||
function rsaPrivate(method, defaultPadding) { | ||
return function(options, buffer) { | ||
const key = options.key || options; | ||
const passphrase = options.passphrase || null; | ||
const padding = options.padding || defaultPadding; | ||
return method(toBuf(key), buffer, padding, passphrase); | ||
}; | ||
} | ||
|
||
const publicEncrypt = rsaPublic(_publicEncrypt, RSA_PKCS1_OAEP_PADDING); | ||
const publicDecrypt = rsaPublic(_publicDecrypt, RSA_PKCS1_PADDING); | ||
const privateEncrypt = rsaPrivate(_privateEncrypt, RSA_PKCS1_PADDING); | ||
const privateDecrypt = rsaPrivate(_privateDecrypt, RSA_PKCS1_OAEP_PADDING); | ||
|
||
function getDecoder(decoder, encoding) { | ||
encoding = normalizeEncoding(encoding); | ||
decoder = decoder || new StringDecoder(encoding); | ||
assert(decoder.encoding === encoding, 'Cannot change encoding'); | ||
return decoder; | ||
} | ||
|
||
function Cipher(cipher, password, options) { | ||
if (!(this instanceof Cipher)) | ||
return new Cipher(cipher, password, options); | ||
this._handle = new CipherBase(true); | ||
|
||
this._handle.init(cipher, toBuf(password)); | ||
this._decoder = null; | ||
|
||
LazyTransform.call(this, options); | ||
} | ||
|
||
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) { | ||
const encoding = getDefaultEncoding(); | ||
inputEncoding = inputEncoding || encoding; | ||
outputEncoding = outputEncoding || 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 || getDefaultEncoding(); | ||
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; | ||
}; | ||
|
||
function Cipheriv(cipher, key, iv, options) { | ||
if (!(this instanceof Cipheriv)) | ||
return new Cipheriv(cipher, key, iv, options); | ||
this._handle = new CipherBase(true); | ||
this._handle.initiv(cipher, toBuf(key), toBuf(iv)); | ||
this._decoder = null; | ||
|
||
LazyTransform.call(this, options); | ||
} | ||
|
||
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; | ||
|
||
|
||
function Decipher(cipher, password, options) { | ||
if (!(this instanceof Decipher)) | ||
return new Decipher(cipher, password, options); | ||
|
||
this._handle = new CipherBase(false); | ||
this._handle.init(cipher, toBuf(password)); | ||
this._decoder = null; | ||
|
||
LazyTransform.call(this, options); | ||
} | ||
|
||
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; | ||
|
||
|
||
function Decipheriv(cipher, key, iv, options) { | ||
if (!(this instanceof Decipheriv)) | ||
return new Decipheriv(cipher, key, iv, options); | ||
|
||
this._handle = new CipherBase(false); | ||
this._handle.initiv(cipher, toBuf(key), toBuf(iv)); | ||
this._decoder = null; | ||
|
||
LazyTransform.call(this, options); | ||
} | ||
|
||
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; | ||
|
||
|
||
module.exports = { | ||
Cipher, | ||
Cipheriv, | ||
Decipher, | ||
Decipheriv, | ||
privateDecrypt, | ||
privateEncrypt, | ||
publicDecrypt, | ||
publicEncrypt, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
'use strict'; | ||
|
||
const { Buffer } = require('buffer'); | ||
const errors = require('internal/errors'); | ||
const { | ||
getDefaultEncoding, | ||
toBuf | ||
} = require('internal/crypto/util'); | ||
const { | ||
DiffieHellman: _DiffieHellman, | ||
DiffieHellmanGroup: _DiffieHellmanGroup, | ||
ECDH: _ECDH | ||
} = process.binding('crypto'); | ||
const { | ||
POINT_CONVERSION_COMPRESSED, | ||
POINT_CONVERSION_HYBRID, | ||
POINT_CONVERSION_UNCOMPRESSED | ||
} = process.binding('constants').crypto; | ||
|
||
const DH_GENERATOR = 2; | ||
|
||
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 errors.TypeError('ERR_INVALID_ARG_TYPE', 'sizeOrKey', | ||
['number', 'string', 'Buffer', 'TypedArray', | ||
'DataView']); | ||
} | ||
|
||
if (keyEncoding) { | ||
if (typeof keyEncoding !== 'string' || | ||
(!Buffer.isEncoding(keyEncoding) && keyEncoding !== 'buffer')) { | ||
genEncoding = generator; | ||
generator = keyEncoding; | ||
keyEncoding = false; | ||
} | ||
} | ||
|
||
const encoding = getDefaultEncoding(); | ||
keyEncoding = keyEncoding || encoding; | ||
genEncoding = genEncoding || 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 _DiffieHellman(sizeOrKey, generator); | ||
Object.defineProperty(this, 'verifyError', { | ||
enumerable: true, | ||
value: this._handle.verifyError, | ||
writable: false | ||
}); | ||
} | ||
|
||
|
||
function DiffieHellmanGroup(name) { | ||
if (!(this instanceof DiffieHellmanGroup)) | ||
return new DiffieHellmanGroup(name); | ||
this._handle = new _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 || getDefaultEncoding(); | ||
if (encoding && encoding !== 'buffer') | ||
keys = keys.toString(encoding); | ||
return keys; | ||
} | ||
|
||
|
||
DiffieHellmanGroup.prototype.computeSecret = | ||
DiffieHellman.prototype.computeSecret = | ||
dhComputeSecret; | ||
|
||
function dhComputeSecret(key, inEnc, outEnc) { | ||
const encoding = getDefaultEncoding(); | ||
inEnc = inEnc || encoding; | ||
outEnc = outEnc || 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 || getDefaultEncoding(); | ||
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 || getDefaultEncoding(); | ||
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 || getDefaultEncoding(); | ||
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 || getDefaultEncoding(); | ||
if (encoding && encoding !== 'buffer') | ||
key = key.toString(encoding); | ||
return key; | ||
} | ||
|
||
|
||
DiffieHellman.prototype.setPublicKey = function setPublicKey(key, encoding) { | ||
encoding = encoding || getDefaultEncoding(); | ||
this._handle.setPublicKey(toBuf(key, encoding)); | ||
return this; | ||
}; | ||
|
||
|
||
DiffieHellman.prototype.setPrivateKey = function setPrivateKey(key, encoding) { | ||
encoding = encoding || getDefaultEncoding(); | ||
this._handle.setPrivateKey(toBuf(key, encoding)); | ||
return this; | ||
}; | ||
|
||
|
||
function ECDH(curve) { | ||
if (typeof curve !== 'string') | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'curve', 'string'); | ||
|
||
this._handle = 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 = POINT_CONVERSION_COMPRESSED; | ||
else if (format === 'hybrid') | ||
f = POINT_CONVERSION_HYBRID; | ||
// Default | ||
else if (format === 'uncompressed') | ||
f = POINT_CONVERSION_UNCOMPRESSED; | ||
else | ||
throw new errors.TypeError('ERR_CRYPTO_ECDH_INVALID_FORMAT', format); | ||
} else { | ||
f = POINT_CONVERSION_UNCOMPRESSED; | ||
} | ||
var key = this._handle.getPublicKey(f); | ||
encoding = encoding || getDefaultEncoding(); | ||
if (encoding && encoding !== 'buffer') | ||
key = key.toString(encoding); | ||
return key; | ||
}; | ||
|
||
module.exports = { | ||
DiffieHellman, | ||
DiffieHellmanGroup, | ||
ECDH | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
'use strict'; | ||
|
||
const { | ||
Hash: _Hash, | ||
Hmac: _Hmac | ||
} = process.binding('crypto'); | ||
|
||
const { | ||
getDefaultEncoding, | ||
toBuf | ||
} = require('internal/crypto/util'); | ||
|
||
const { | ||
isArrayBufferView | ||
} = process.binding('util'); | ||
|
||
const { Buffer } = require('buffer'); | ||
|
||
const errors = require('internal/errors'); | ||
const { inherits } = require('util'); | ||
const { normalizeEncoding } = require('internal/util'); | ||
const LazyTransform = require('internal/streams/lazy_transform'); | ||
const kState = Symbol('state'); | ||
const kFinalized = Symbol('finalized'); | ||
|
||
function Hash(algorithm, options) { | ||
if (!(this instanceof Hash)) | ||
return new Hash(algorithm, options); | ||
if (typeof algorithm !== 'string') | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'algorithm', 'string'); | ||
this._handle = new _Hash(algorithm); | ||
this[kState] = { | ||
[kFinalized]: false | ||
}; | ||
LazyTransform.call(this, options); | ||
} | ||
|
||
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) { | ||
const state = this[kState]; | ||
if (state[kFinalized]) | ||
throw new errors.Error('ERR_CRYPTO_HASH_FINALIZED'); | ||
|
||
if (typeof data !== 'string' && !isArrayBufferView(data)) { | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'data', | ||
['string', 'TypedArray', 'DataView']); | ||
} | ||
|
||
if (!this._handle.update(data, encoding || getDefaultEncoding())) | ||
throw new errors.Error('ERR_CRYPTO_HASH_UPDATE_FAILED'); | ||
return this; | ||
}; | ||
|
||
|
||
Hash.prototype.digest = function digest(outputEncoding) { | ||
const state = this[kState]; | ||
if (state[kFinalized]) | ||
throw new errors.Error('ERR_CRYPTO_HASH_FINALIZED'); | ||
outputEncoding = outputEncoding || getDefaultEncoding(); | ||
if (normalizeEncoding(outputEncoding) === 'utf16le') | ||
throw new errors.Error('ERR_CRYPTO_HASH_DIGEST_NO_UTF16'); | ||
|
||
// Explicit conversion for backward compatibility. | ||
const ret = this._handle.digest(`${outputEncoding}`); | ||
state[kFinalized] = true; | ||
return ret; | ||
}; | ||
|
||
|
||
function Hmac(hmac, key, options) { | ||
if (!(this instanceof Hmac)) | ||
return new Hmac(hmac, key, options); | ||
if (typeof hmac !== 'string') | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'hmac', 'string'); | ||
if (typeof key !== 'string' && !isArrayBufferView(key)) { | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'key', | ||
['string', 'TypedArray', 'DataView']); | ||
} | ||
this._handle = new _Hmac(); | ||
this._handle.init(hmac, toBuf(key)); | ||
this[kState] = { | ||
[kFinalized]: false | ||
}; | ||
LazyTransform.call(this, options); | ||
} | ||
|
||
inherits(Hmac, LazyTransform); | ||
|
||
Hmac.prototype.update = Hash.prototype.update; | ||
|
||
Hmac.prototype.digest = function digest(outputEncoding) { | ||
const state = this[kState]; | ||
outputEncoding = outputEncoding || getDefaultEncoding(); | ||
if (normalizeEncoding(outputEncoding) === 'utf16le') | ||
throw new errors.Error('ERR_CRYPTO_HASH_DIGEST_NO_UTF16'); | ||
|
||
if (state[kFinalized]) { | ||
const buf = Buffer.from(''); | ||
return outputEncoding === 'buffer' ? buf : buf.toString(outputEncoding); | ||
} | ||
|
||
// Explicit conversion for backward compatibility. | ||
const ret = this._handle.digest(`${outputEncoding}`); | ||
state[kFinalized] = true; | ||
return ret; | ||
}; | ||
|
||
Hmac.prototype._flush = Hash.prototype._flush; | ||
Hmac.prototype._transform = Hash.prototype._transform; | ||
|
||
module.exports = { | ||
Hash, | ||
Hmac | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
'use strict'; | ||
|
||
const errors = require('internal/errors'); | ||
const { | ||
getDefaultEncoding, | ||
toBuf | ||
} = require('internal/crypto/util'); | ||
const { | ||
PBKDF2 | ||
} = process.binding('crypto'); | ||
|
||
function pbkdf2(password, salt, iterations, keylen, digest, callback) { | ||
if (typeof digest === 'function') { | ||
callback = digest; | ||
digest = undefined; | ||
} | ||
|
||
if (typeof callback !== 'function') | ||
throw new errors.TypeError('ERR_INVALID_CALLBACK'); | ||
|
||
return _pbkdf2(password, salt, iterations, keylen, digest, callback); | ||
} | ||
|
||
function pbkdf2Sync(password, salt, iterations, keylen, digest) { | ||
return _pbkdf2(password, salt, iterations, keylen, digest); | ||
} | ||
|
||
function _pbkdf2(password, salt, iterations, keylen, digest, callback) { | ||
|
||
if (digest !== null && typeof digest !== 'string') | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'digest', | ||
['string', 'null']); | ||
|
||
password = toBuf(password); | ||
salt = toBuf(salt); | ||
|
||
const encoding = getDefaultEncoding(); | ||
|
||
if (encoding === 'buffer') | ||
return PBKDF2(password, salt, iterations, keylen, digest, callback); | ||
|
||
// at this point, we need to handle encodings. | ||
if (callback) { | ||
function next(er, ret) { | ||
if (ret) | ||
ret = ret.toString(encoding); | ||
callback(er, ret); | ||
} | ||
PBKDF2(password, salt, iterations, keylen, digest, next); | ||
} else { | ||
var ret = PBKDF2(password, salt, iterations, keylen, digest); | ||
return ret.toString(encoding); | ||
} | ||
} | ||
|
||
module.exports = { | ||
pbkdf2, | ||
pbkdf2Sync | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
'use strict'; | ||
|
||
const errors = require('internal/errors'); | ||
const { isArrayBufferView } = process.binding('util'); | ||
const { | ||
randomBytes, | ||
randomFill: _randomFill | ||
} = process.binding('crypto'); | ||
|
||
const { kMaxLength } = require('buffer'); | ||
const kMaxUint32 = Math.pow(2, 32) - 1; | ||
|
||
function assertOffset(offset, length) { | ||
if (typeof offset !== 'number' || offset !== offset) { | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'offset', 'number'); | ||
} | ||
|
||
if (offset > kMaxUint32 || offset < 0) { | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'offset', 'uint32'); | ||
} | ||
|
||
if (offset > kMaxLength || offset > length) { | ||
throw new errors.RangeError('ERR_OUT_OF_RANGE', 'offset'); | ||
} | ||
} | ||
|
||
function assertSize(size, offset, length) { | ||
if (typeof size !== 'number' || size !== size) { | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'size', 'number'); | ||
} | ||
|
||
if (size > kMaxUint32 || size < 0) { | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'size', 'uint32'); | ||
} | ||
|
||
if (size + offset > length || size > kMaxLength) { | ||
throw new errors.RangeError('ERR_OUT_OF_RANGE', 'size'); | ||
} | ||
} | ||
|
||
function randomFillSync(buf, offset = 0, size) { | ||
if (!isArrayBufferView(buf)) { | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', | ||
'buf', 'ArrayBufferView'); | ||
} | ||
|
||
const elementSize = buf.BYTES_PER_ELEMENT || 1; | ||
|
||
offset *= elementSize; | ||
assertOffset(offset, buf.byteLength); | ||
|
||
if (size === undefined) { | ||
size = buf.byteLength - offset; | ||
} else { | ||
size *= elementSize; | ||
} | ||
|
||
assertSize(size, offset, buf.byteLength); | ||
|
||
return _randomFill(buf, offset, size); | ||
} | ||
|
||
function randomFill(buf, offset, size, cb) { | ||
if (!isArrayBufferView(buf)) { | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', | ||
'buf', 'ArrayBufferView'); | ||
} | ||
|
||
const elementSize = buf.BYTES_PER_ELEMENT || 1; | ||
|
||
if (typeof offset === 'function') { | ||
cb = offset; | ||
offset = 0; | ||
size = buf.bytesLength; | ||
} else if (typeof size === 'function') { | ||
cb = size; | ||
offset *= elementSize; | ||
size = buf.byteLength - offset; | ||
} else if (typeof cb !== 'function') { | ||
throw new errors.TypeError('ERR_INVALID_CALLBACK'); | ||
} | ||
if (size === undefined) { | ||
size = buf.byteLength - offset; | ||
} else { | ||
size *= elementSize; | ||
} | ||
|
||
assertOffset(offset, buf.byteLength); | ||
assertSize(size, offset, buf.byteLength); | ||
|
||
return _randomFill(buf, offset, size, cb); | ||
} | ||
|
||
module.exports = { | ||
randomBytes, | ||
randomFill, | ||
randomFillSync | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
'use strict'; | ||
|
||
const errors = require('internal/errors'); | ||
const { | ||
Sign: _Sign, | ||
Verify: _Verify | ||
} = process.binding('crypto'); | ||
const { | ||
RSA_PSS_SALTLEN_AUTO, | ||
RSA_PKCS1_PADDING | ||
} = process.binding('constants').crypto; | ||
const { | ||
getDefaultEncoding, | ||
toBuf | ||
} = require('internal/crypto/util'); | ||
const { Writable } = require('stream'); | ||
const { inherits } = require('util'); | ||
|
||
function Sign(algorithm, options) { | ||
if (!(this instanceof Sign)) | ||
return new Sign(algorithm, options); | ||
this._handle = new _Sign(); | ||
this._handle.init(algorithm); | ||
|
||
Writable.call(this, options); | ||
} | ||
|
||
inherits(Sign, Writable); | ||
|
||
Sign.prototype._write = function _write(chunk, encoding, callback) { | ||
this._handle.update(chunk, encoding); | ||
callback(); | ||
}; | ||
|
||
Sign.prototype.update = function update(data, encoding) { | ||
encoding = encoding || getDefaultEncoding(); | ||
this._handle.update(data, encoding); | ||
return this; | ||
}; | ||
|
||
Sign.prototype.sign = function sign(options, encoding) { | ||
if (!options) | ||
throw new errors.Error('ERR_CRYPTO_SIGN_KEY_REQUIRED'); | ||
|
||
var key = options.key || options; | ||
var passphrase = options.passphrase || null; | ||
|
||
// Options specific to RSA | ||
var rsaPadding = RSA_PKCS1_PADDING; | ||
if (options.hasOwnProperty('padding')) { | ||
if (options.padding === options.padding >> 0) { | ||
rsaPadding = options.padding; | ||
} else { | ||
throw new errors.TypeError('ERR_INVALID_OPT_VALUE', | ||
'padding', | ||
options.padding); | ||
} | ||
} | ||
|
||
var pssSaltLength = RSA_PSS_SALTLEN_AUTO; | ||
if (options.hasOwnProperty('saltLength')) { | ||
if (options.saltLength === options.saltLength >> 0) { | ||
pssSaltLength = options.saltLength; | ||
} else { | ||
throw new errors.TypeError('ERR_INVALID_OPT_VALUE', | ||
'saltLength', | ||
options.saltLength); | ||
} | ||
} | ||
|
||
var ret = this._handle.sign(toBuf(key), passphrase, rsaPadding, | ||
pssSaltLength); | ||
|
||
encoding = encoding || getDefaultEncoding(); | ||
if (encoding && encoding !== 'buffer') | ||
ret = ret.toString(encoding); | ||
|
||
return ret; | ||
}; | ||
|
||
|
||
function Verify(algorithm, options) { | ||
if (!(this instanceof Verify)) | ||
return new Verify(algorithm, options); | ||
|
||
this._handle = new _Verify(); | ||
this._handle.init(algorithm); | ||
|
||
Writable.call(this, options); | ||
} | ||
|
||
inherits(Verify, 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 || getDefaultEncoding(); | ||
|
||
// Options specific to RSA | ||
var rsaPadding = RSA_PKCS1_PADDING; | ||
if (options.hasOwnProperty('padding')) { | ||
if (options.padding === options.padding >> 0) { | ||
rsaPadding = options.padding; | ||
} else { | ||
throw new errors.TypeError('ERR_INVALID_OPT_VALUE', | ||
'padding', | ||
options.padding); | ||
} | ||
} | ||
|
||
var pssSaltLength = RSA_PSS_SALTLEN_AUTO; | ||
if (options.hasOwnProperty('saltLength')) { | ||
if (options.saltLength === options.saltLength >> 0) { | ||
pssSaltLength = options.saltLength; | ||
} else { | ||
throw new errors.TypeError('ERR_INVALID_OPT_VALUE', | ||
'saltLength', | ||
options.saltLength); | ||
} | ||
} | ||
|
||
return this._handle.verify(toBuf(key), toBuf(signature, sigEncoding), | ||
rsaPadding, pssSaltLength); | ||
}; | ||
|
||
module.exports = { | ||
Sign, | ||
Verify | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
'use strict'; | ||
|
||
const { | ||
getCiphers: _getCiphers, | ||
getCurves: _getCurves, | ||
getHashes: _getHashes, | ||
setEngine: _setEngine | ||
} = process.binding('crypto'); | ||
|
||
const { | ||
ENGINE_METHOD_ALL | ||
} = process.binding('constants').crypto; | ||
|
||
const errors = require('internal/errors'); | ||
const { Buffer } = require('buffer'); | ||
const { | ||
cachedResult, | ||
filterDuplicateStrings | ||
} = require('internal/util'); | ||
|
||
var defaultEncoding = 'buffer'; | ||
|
||
function setDefaultEncoding(val) { | ||
defaultEncoding = val; | ||
} | ||
|
||
function getDefaultEncoding() { | ||
return defaultEncoding; | ||
} | ||
|
||
// 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; | ||
} | ||
|
||
const getCiphers = cachedResult(() => filterDuplicateStrings(_getCiphers())); | ||
const getHashes = cachedResult(() => filterDuplicateStrings(_getHashes())); | ||
const getCurves = cachedResult(() => filterDuplicateStrings(_getCurves())); | ||
|
||
function setEngine(id, flags) { | ||
if (typeof id !== 'string') | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'id', 'string'); | ||
|
||
if (flags && typeof flags !== 'number') | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'flags', 'number'); | ||
flags = flags >>> 0; | ||
|
||
// Use provided engine for everything by default | ||
if (flags === 0) | ||
flags = ENGINE_METHOD_ALL; | ||
|
||
return _setEngine(id, flags); | ||
} | ||
|
||
module.exports = { | ||
getCiphers, | ||
getCurves, | ||
getDefaultEncoding, | ||
getHashes, | ||
setDefaultEncoding, | ||
setEngine, | ||
toBuf | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters