summaryrefslogtreecommitdiff
path: root/lib/internal/crypto/hash.js
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2017-09-06 08:10:34 -0700
committerJames M Snell <jasnell@gmail.com>2017-09-18 08:10:59 -0700
commitc75f87cc4c8d3699e081d37bb5bf47a70d830fdb (patch)
tree9d79319f568ff43e36e05a8d2634130adfacfb74 /lib/internal/crypto/hash.js
parent8fa5fcc0ba74c23490c34da1a6c6e9a454280740 (diff)
downloadandroid-node-v8-c75f87cc4c8d3699e081d37bb5bf47a70d830fdb.tar.gz
android-node-v8-c75f87cc4c8d3699e081d37bb5bf47a70d830fdb.tar.bz2
android-node-v8-c75f87cc4c8d3699e081d37bb5bf47a70d830fdb.zip
crypto: refactor the crypto module
* 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: https://github.com/nodejs/node/pull/15231 Reviewed-By: Michaƫl Zasso <targos@protonmail.com> Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Diffstat (limited to 'lib/internal/crypto/hash.js')
-rw-r--r--lib/internal/crypto/hash.js125
1 files changed, 125 insertions, 0 deletions
diff --git a/lib/internal/crypto/hash.js b/lib/internal/crypto/hash.js
new file mode 100644
index 0000000000..12b3e1e78e
--- /dev/null
+++ b/lib/internal/crypto/hash.js
@@ -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
+};