react-native-quick-crypto
Version:
A fast implementation of Node's `crypto` module written in C/C++ JSI
89 lines (87 loc) • 3.78 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.pbkdf2 = pbkdf2;
exports.pbkdf2DeriveBits = pbkdf2DeriveBits;
exports.pbkdf2Sync = pbkdf2Sync;
var _reactNativeBuffer = require("@craftzdog/react-native-buffer");
var _reactNativeNitroModules = require("react-native-nitro-modules");
var _utils = require("./utils");
var _util = require("util");
const WRONG_PASS = 'Password must be a string, a Buffer, a typed array or a DataView';
const WRONG_SALT = `Salt must be a string, a Buffer, a typed array or a DataView`;
// to use native bits in sub-functions, use getNative(). don't call it at top-level!
let native;
function getNative() {
if (native == null) {
// lazy-load the Nitro HybridObject
native = _reactNativeNitroModules.NitroModules.createHybridObject('Pbkdf2');
}
return native;
}
function sanitizeInput(input, errorMsg) {
try {
return (0, _utils.binaryLikeToArrayBuffer)(input);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (_e) {
throw new Error(errorMsg);
}
}
function pbkdf2(password, salt, iterations, keylen, digest, callback) {
if (callback === undefined || typeof callback !== 'function') {
throw new Error('No callback provided to pbkdf2');
}
const sanitizedPassword = sanitizeInput(password, WRONG_PASS);
const sanitizedSalt = sanitizeInput(salt, WRONG_SALT);
const normalizedDigest = (0, _utils.normalizeHashName)(digest, _utils.HashContext.Node);
getNative();
native.pbkdf2(sanitizedPassword, sanitizedSalt, iterations, keylen, normalizedDigest).then(res => {
callback(null, _reactNativeBuffer.Buffer.from(res));
}, e => {
callback(e);
});
}
function pbkdf2Sync(password, salt, iterations, keylen, digest) {
const sanitizedPassword = sanitizeInput(password, WRONG_PASS);
const sanitizedSalt = sanitizeInput(salt, WRONG_SALT);
const algo = digest ? (0, _utils.normalizeHashName)(digest, _utils.HashContext.Node) : 'sha1';
getNative();
const result = native.pbkdf2Sync(sanitizedPassword, sanitizedSalt, iterations, keylen, algo);
return _reactNativeBuffer.Buffer.from(result);
}
// We need this because the typescript overload signatures in pbkdf2() above do
// not play nice with promisify() below.
const pbkdf2WithDigest = (password, salt, iterations, keylen, digest, callback) => pbkdf2(password, salt, iterations, keylen, digest, callback);
const pbkdf2Promise = (0, _util.promisify)(pbkdf2WithDigest);
async function pbkdf2DeriveBits(algorithm, baseKey, length) {
const {
iterations,
hash,
salt
} = algorithm;
const normalizedHash = (0, _utils.normalizeHashName)(hash);
if (!normalizedHash) {
throw (0, _utils.lazyDOMException)('hash cannot be blank', 'OperationError');
}
if (!iterations || iterations === 0) {
throw (0, _utils.lazyDOMException)('iterations cannot be zero', 'OperationError');
}
if (!salt) {
throw (0, _utils.lazyDOMException)(WRONG_SALT, 'OperationError');
}
const raw = baseKey.keyObject.export();
if (length === 0) throw (0, _utils.lazyDOMException)('length cannot be zero', 'OperationError');
if (length === null) throw (0, _utils.lazyDOMException)('length cannot be null', 'OperationError');
if (length % 8) {
throw (0, _utils.lazyDOMException)('length must be a multiple of 8', 'OperationError');
}
const sanitizedPassword = sanitizeInput(raw, WRONG_PASS);
const sanitizedSalt = sanitizeInput(salt, WRONG_SALT);
const result = await pbkdf2Promise(sanitizedPassword, sanitizedSalt, iterations, length / 8, normalizedHash);
if (!result) {
throw (0, _utils.lazyDOMException)('received bad result from pbkdf2()', 'OperationError');
}
return (0, _utils.bufferLikeToArrayBuffer)(result);
}
//# sourceMappingURL=pbkdf2.js.map