UNPKG

react-native-quick-crypto

Version:

A fast implementation of Node's `crypto` module written in C/C++ JSI

108 lines (96 loc) 3.1 kB
import { NativeQuickCrypto } from './NativeQuickCrypto/NativeQuickCrypto'; import type { InternalHmac } from './NativeQuickCrypto/hmac'; import { type Encoding, toArrayBuffer, type BinaryLike, binaryLikeToArrayBuffer, } from './Utils'; import Stream from 'readable-stream'; import { Buffer } from '@craftzdog/react-native-buffer'; const createInternalHmac = NativeQuickCrypto.createHmac; export function createHmac( algorithm: string, key: BinaryLike, options?: Stream.TransformOptions, ) { return new Hmac(algorithm, key, options); } class Hmac extends Stream.Transform { private internalHmac: InternalHmac; private isFinalized: boolean = false; constructor( algorithm: string, key: BinaryLike, // eslint-disable-next-line @typescript-eslint/no-unused-vars _options?: Stream.TransformOptions, ) { super(); const keyAsString = binaryLikeToArrayBuffer(key); if (keyAsString === undefined) { throw 'Wrong key type'; } this.internalHmac = createInternalHmac( algorithm, keyAsString as ArrayBuffer, ); } /** * 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 v0.1.94 * @param inputEncoding The `encoding` of the `data` string. */ update(data: string | BinaryLike, inputEncoding?: Encoding): Hmac { if (data instanceof ArrayBuffer) { this.internalHmac.update(data); return this; } if (typeof data === 'string') { const buffer = Buffer.from(data, inputEncoding); this.internalHmac.update(toArrayBuffer(buffer)); return this; } this.internalHmac.update(binaryLikeToArrayBuffer(data)); return this; } _transform( chunk: string | BinaryLike, encoding: Encoding, callback: () => void, ) { this.update(chunk, encoding); callback(); } _flush(callback: () => void) { this.push(this.digest()); callback(); } /** * 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 v0.1.94 * @param encoding The `encoding` of the return value. */ digest(): Buffer; digest(encoding: 'buffer'): Buffer; digest(encoding: Encoding): string; digest(encoding?: Encoding | 'buffer'): string | Buffer { const result: ArrayBuffer = this.isFinalized ? new ArrayBuffer(0) : this.internalHmac.digest(); this.isFinalized = true; if (encoding && encoding !== 'buffer') { return Buffer.from(result).toString(encoding); } return Buffer.from(result); } }