react-native-quick-crypto
Version:
A fast implementation of Node's `crypto` module written in C/C++ JSI
88 lines (85 loc) • 4.21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.argon2 = argon2;
exports.argon2Sync = argon2Sync;
var _reactNativeBuffer = require("@craftzdog/react-native-buffer");
var _reactNativeNitroModules = require("react-native-nitro-modules");
var _utils = require("./utils");
let native;
function getNative() {
if (native == null) {
native = _reactNativeNitroModules.NitroModules.createHybridObject('Argon2');
}
return native;
}
const ARGON2_VERSION = 0x13; // v1.3
// RFC 9106 § 3.1: Argon2 input/parameter constraints.
// p (parallelism) 1 ≤ p ≤ 2^24 - 1
// T (tag length) 4 ≤ T ≤ 2^32 - 1
// m (memory in KiB) 8*p ≤ m ≤ 2^32 - 1
// t (passes) 1 ≤ t ≤ 2^32 - 1
// |salt| (nonce) 8 ≤ |s| ≤ 2^32 - 1
// v (version) 0x10 (v1.0) or 0x13 (v1.3)
const ARGON2_MAX_U24 = 0xff_ffff;
const ARGON2_MAX_U32 = 0xffff_ffff;
function isUInt(value, max) {
return typeof value === 'number' && Number.isFinite(value) && Number.isInteger(value) && value >= 0 && value <= max;
}
function validateAlgorithm(algorithm) {
if (algorithm !== 'argon2d' && algorithm !== 'argon2i' && algorithm !== 'argon2id') {
throw new TypeError(`Unknown argon2 algorithm: ${algorithm}`);
}
}
// Returns the resolved nonce ArrayBuffer so the caller can pass it
// straight to native without re-resolving `params.nonce`.
function validateArgon2Params(params, version) {
if (!isUInt(params.parallelism, ARGON2_MAX_U24) || params.parallelism < 1) {
throw new RangeError(`Invalid Argon2 parallelism: ${params.parallelism} ` + `(RFC 9106: 1 ≤ p ≤ 2^24 - 1)`);
}
if (!isUInt(params.tagLength, ARGON2_MAX_U32) || params.tagLength < 4) {
throw new RangeError(`Invalid Argon2 tagLength: ${params.tagLength} ` + `(RFC 9106: 4 ≤ T ≤ 2^32 - 1)`);
}
const minMemory = 8 * params.parallelism;
if (!isUInt(params.memory, ARGON2_MAX_U32) || params.memory < minMemory) {
throw new RangeError(`Invalid Argon2 memory: ${params.memory} KiB ` + `(RFC 9106: 8 * p (= ${minMemory}) ≤ m ≤ 2^32 - 1)`);
}
if (!isUInt(params.passes, ARGON2_MAX_U32) || params.passes < 1) {
throw new RangeError(`Invalid Argon2 passes: ${params.passes} ` + `(RFC 9106: 1 ≤ t ≤ 2^32 - 1)`);
}
if (version !== 0x10 && version !== 0x13) {
throw new RangeError(`Invalid Argon2 version: 0x${version.toString(16)} ` + `(RFC 9106: 0x10 or 0x13)`);
}
// Salt (nonce) must be 8..2^32 - 1 bytes — measured against the resolved
// ArrayBuffer because BinaryLike accepts strings whose UTF-8 length is
// what actually reaches OpenSSL.
const nonceAB = (0, _utils.binaryLikeToArrayBuffer)(params.nonce);
if (nonceAB.byteLength < 8 || nonceAB.byteLength > ARGON2_MAX_U32) {
throw new RangeError(`Invalid Argon2 nonce length: ${nonceAB.byteLength} bytes ` + `(RFC 9106: 8 ≤ |s| ≤ 2^32 - 1)`);
}
return nonceAB;
}
function toAB(value) {
return (0, _utils.binaryLikeToArrayBuffer)(value);
}
function argon2Sync(algorithm, params) {
validateAlgorithm(algorithm);
const version = params.version ?? ARGON2_VERSION;
const nonceAB = validateArgon2Params(params, version);
const result = getNative().hashSync(algorithm, toAB(params.message), nonceAB, params.parallelism, params.tagLength, params.memory, params.passes, version, params.secret ? toAB(params.secret) : undefined, params.associatedData ? toAB(params.associatedData) : undefined);
return _reactNativeBuffer.Buffer.from(result);
}
function argon2(algorithm, params, callback) {
validateAlgorithm(algorithm);
const version = params.version ?? ARGON2_VERSION;
let nonceAB;
try {
nonceAB = validateArgon2Params(params, version);
} catch (err) {
callback(err, _reactNativeBuffer.Buffer.alloc(0));
return;
}
getNative().hash(algorithm, toAB(params.message), nonceAB, params.parallelism, params.tagLength, params.memory, params.passes, version, params.secret ? toAB(params.secret) : undefined, params.associatedData ? toAB(params.associatedData) : undefined).then(ab => callback(null, _reactNativeBuffer.Buffer.from(ab))).catch(err => callback(err, _reactNativeBuffer.Buffer.alloc(0)));
}
//# sourceMappingURL=argon2.js.map