react-native-quick-crypto
Version:
A fast implementation of Node's `crypto` module written in C/C++ JSI
180 lines (171 loc) • 5.68 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Verify = exports.Sign = void 0;
exports.createSign = createSign;
exports.createVerify = createVerify;
var _reactNativeBuffer = require("@craftzdog/react-native-buffer");
var _reactNativeNitroModules = require("react-native-nitro-modules");
var _classes = require("./classes");
var _utils = require("./utils");
var _utils2 = require("../utils");
function prepareKey(key, isPublic) {
// Already a KeyObject
if (key instanceof _classes.KeyObject) {
if (isPublic) {
if (key.type === 'secret') {
throw new Error('Cannot use secret key for signature verification');
}
} else {
if (key.type !== 'private') {
throw new Error('Key must be a private key for signing');
}
}
return {
keyObject: key
};
}
// CryptoKey - extract KeyObject
if ((0, _utils.isCryptoKey)(key)) {
const cryptoKey = key;
return prepareKey(cryptoKey.keyObject, isPublic);
}
// Raw string or buffer - create KeyObject
if ((0, _utils2.isStringOrBuffer)(key)) {
const isPem = typeof key === 'string' && key.includes('-----BEGIN');
const format = isPem ? _utils2.KFormatType.PEM : undefined;
const type = isPublic ? 'public' : 'private';
const keyData = (0, _utils2.binaryLikeToArrayBuffer)(key);
const keyObject = _classes.KeyObject.createKeyObject(type, keyData, format);
return {
keyObject
};
}
// KeyInputObject with options
if (typeof key === 'object' && 'key' in key) {
const keyObj = key;
const {
key: data,
format,
type,
padding,
saltLength,
dsaEncoding
} = keyObj;
// Nested KeyObject
if (data instanceof _classes.KeyObject) {
return {
keyObject: data,
options: {
padding,
saltLength,
dsaEncoding
}
};
}
// Nested CryptoKey
if ((0, _utils.isCryptoKey)(data)) {
return {
keyObject: data.keyObject,
options: {
padding,
saltLength,
dsaEncoding
}
};
}
if (!(0, _utils2.isStringOrBuffer)(data)) {
throw new Error('Invalid key data type');
}
// Determine format
const isPem = format === 'pem' || typeof data === 'string' && data.includes('-----BEGIN');
const kFormat = isPem ? _utils2.KFormatType.PEM : format === 'der' ? _utils2.KFormatType.DER : undefined;
// Determine encoding type
let kType;
if (type === 'pkcs8') kType = _utils2.KeyEncoding.PKCS8;else if (type === 'pkcs1') kType = _utils2.KeyEncoding.PKCS1;else if (type === 'sec1') kType = _utils2.KeyEncoding.SEC1;else if (type === 'spki') kType = _utils2.KeyEncoding.SPKI;
const keyType = isPublic ? 'public' : 'private';
// Always convert to ArrayBuffer to avoid Nitro bridge string truncation bug
const originalLength = typeof data === 'string' ? data.length : data.byteLength;
const keyData = (0, _utils2.binaryLikeToArrayBuffer)(data);
console.log(`[prepareKey KeyInputObject] ${keyType} key, original length: ${originalLength}, ArrayBuffer size: ${keyData.byteLength}`);
const keyObject = _classes.KeyObject.createKeyObject(keyType, keyData, kFormat, kType);
return {
keyObject,
options: {
padding,
saltLength,
dsaEncoding
}
};
}
throw new Error('Invalid key input');
}
function dsaEncodingToNumber(dsaEncoding) {
if (dsaEncoding === 'der') return 0;
if (dsaEncoding === 'ieee-p1363') return 1;
return undefined;
}
class Sign {
constructor(algorithm) {
this.handle = _reactNativeNitroModules.NitroModules.createHybridObject('SignHandle');
this.handle.init(algorithm);
}
update(data) {
const dataBuffer = (0, _utils2.binaryLikeToArrayBuffer)(data);
this.handle.update(dataBuffer);
return this;
}
sign(privateKey, outputEncoding) {
if (privateKey === null || privateKey === undefined) {
throw new Error('Private key is required');
}
const {
keyObject,
options
} = prepareKey(privateKey, false);
const signature = this.handle.sign(keyObject.handle, options?.padding, options?.saltLength, dsaEncodingToNumber(options?.dsaEncoding));
const buf = _reactNativeBuffer.Buffer.from(signature);
if (outputEncoding) {
return buf.toString(outputEncoding);
}
return buf;
}
}
exports.Sign = Sign;
class Verify {
constructor(algorithm) {
this.handle = _reactNativeNitroModules.NitroModules.createHybridObject('VerifyHandle');
this.handle.init(algorithm);
}
update(data) {
const dataBuffer = (0, _utils2.binaryLikeToArrayBuffer)(data);
this.handle.update(dataBuffer);
return this;
}
verify(publicKey, signature, signatureEncoding) {
if (publicKey === null || publicKey === undefined) {
throw new Error('Public key is required');
}
const {
keyObject,
options
} = prepareKey(publicKey, true);
// Convert signature to ArrayBuffer
let sigBuffer;
if (signatureEncoding && typeof signature === 'string') {
sigBuffer = (0, _utils2.binaryLikeToArrayBuffer)(_reactNativeBuffer.Buffer.from(signature, signatureEncoding));
} else {
sigBuffer = (0, _utils2.binaryLikeToArrayBuffer)(signature);
}
return this.handle.verify(keyObject.handle, sigBuffer, options?.padding, options?.saltLength, dsaEncodingToNumber(options?.dsaEncoding));
}
}
exports.Verify = Verify;
function createSign(algorithm) {
return new Sign(algorithm);
}
function createVerify(algorithm) {
return new Verify(algorithm);
}
//# sourceMappingURL=signVerify.js.map