react-native-quick-crypto
Version:
A fast implementation of Node's `crypto` module written in C/C++ JSI
115 lines (106 loc) • 3.93 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createHmac = createHmac;
exports.hmacExports = void 0;
var _reactNativeBuffer = require("@craftzdog/react-native-buffer");
var _readableStream = require("readable-stream");
var _reactNativeNitroModules = require("react-native-nitro-modules");
var _conversion = require("./utils/conversion");
class Hmac extends _readableStream.Stream.Transform {
validate(args) {
if (typeof args.algorithm !== 'string' || args.algorithm.length === 0) throw new Error('Algorithm must be a non-empty string');
if (args.key === null || args.key === undefined) throw new Error('Key must not be null or undefined');
}
/**
* @internal use `createHmac()` instead
*/
constructor(args) {
super(args.options);
this.validate(args);
this.algorithm = args.algorithm;
this.key = args.key;
this.native = _reactNativeNitroModules.NitroModules.createHybridObject('Hmac');
this.native.createHmac(this.algorithm, (0, _conversion.binaryLikeToArrayBuffer)(this.key));
}
/**
* Updates the `Hmac` content with the given `data`, the encoding of which is given in `inputEncoding`.
* If `encoding` is not provided, and the `data` is a string, an encoding of `'utf8'` is enforced.
* If `data` is a `Buffer`, `TypedArray`, or`DataView`, then `inputEncoding` is ignored.
*
* This can be called many times with new data as it is streamed.
* @since v1.0.0
* @param inputEncoding The `encoding` of the `data` string.
*/
update(data, inputEncoding) {
const defaultEncoding = 'utf8';
inputEncoding = inputEncoding ?? defaultEncoding;
// Optimize: pass UTF-8 strings directly to C++ without conversion
if (typeof data === 'string' && inputEncoding === 'utf8') {
this.native.update(data);
} else {
this.native.update((0, _conversion.binaryLikeToArrayBuffer)(data, inputEncoding));
}
return this; // to support chaining syntax createHmac().update().digest()
}
/**
* Calculates the HMAC digest of all of the data passed using `hmac.update()`.
* If `encoding` is provided a string is returned; otherwise a `Buffer` is returned;
*
* The `Hmac` object can not be used again after `hmac.digest()` has been
* called. Multiple calls to `hmac.digest()` will result in an error being thrown.
* @since v1.0.0
* @param encoding The `encoding` of the return value.
*/
digest(encoding) {
const nativeDigest = this.native.digest();
if (encoding && encoding !== 'buffer') {
return (0, _conversion.ab2str)(nativeDigest, encoding);
}
return _reactNativeBuffer.Buffer.from(nativeDigest);
}
// stream interface
_transform(chunk, encoding, callback) {
this.update(chunk, encoding);
callback();
}
_flush(callback) {
this.push(this.digest());
callback();
}
}
/**
* Creates and returns an `Hmac` object that uses the given `algorithm` and `key`.
* Optional `options` argument controls stream behavior.
*
* The `algorithm` is dependent on the available algorithms supported by the
* version of OpenSSL on the platform. Examples are `'sha256'`, `'sha512'`, etc.
* On recent releases of OpenSSL, `openssl list -digest-algorithms` will
* display the available digest algorithms.
*
* Example: generating the sha256 HMAC of a file
*
* ```js
* import crypto from 'react-native-quick-crypto';
*
* const hmac = crypto.createHmac('sha256', 'secret-key');
* hmac.update('message to hash');
* const digest = hmac.digest('hex');
* console.log(digest); // prints HMAC digest in hexadecimal format
* ```
* @since v1.0.0
* @param options `stream.transform` options
*/
function createHmac(algorithm, key, options) {
// @ts-expect-error private constructor
return new Hmac({
algorithm,
key,
options
});
}
const hmacExports = exports.hmacExports = {
createHmac
};
//# sourceMappingURL=hmac.js.map