react-native-quick-crypto
Version:
A fast implementation of Node's `crypto` module written in C/C++ JSI
275 lines (261 loc) • 9.36 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ecExportKey = ecExportKey;
exports.ecGenerateKey = void 0;
exports.ecImportKey = ecImportKey;
exports.ecdsaSignVerify = void 0;
var _Cipher = require("./Cipher");
var _NativeQuickCrypto = require("./NativeQuickCrypto/NativeQuickCrypto");
var _sig = require("./NativeQuickCrypto/sig");
var _Utils = require("./Utils");
var _keys = require("./keys");
// const {
// ArrayPrototypeIncludes,
// ObjectKeys,
// SafeSet,
// } = primordials;
// const {
// ECKeyExportJob,
// KeyObjectHandle,
// SignJob,
// kCryptoJobAsync,
// kKeyTypePrivate,
// kSignJobModeSign,
// kSignJobModeVerify,
// kSigEncP1363,
// } = internalBinding('crypto');
// const {
// getUsagesUnion,
// hasAnyNotIn,
// jobPromise,
// normalizeHashName,
// validateKeyOps,
// kHandle,
// kKeyObject,
// kNamedCurveAliases,
// } = require('internal/crypto/util');
// const {
// lazyDOMException,
// promisify,
// } = require('internal/util');
// const {
// generateKeyPair: _generateKeyPair,
// } = require('internal/crypto/keygen');
// const {
// InternalCryptoKey,
// PrivateKeyObject,
// PublicKeyObject,
// createPrivateKey,
// createPublicKey,
// } = require('internal/crypto/keys');
// const generateKeyPair = promisify(_generateKeyPair);
function verifyAcceptableEcKeyUse(name, isPublic, usages) {
let checkSet;
switch (name) {
case 'ECDH':
checkSet = isPublic ? [] : ['deriveKey', 'deriveBits'];
break;
case 'ECDSA':
checkSet = isPublic ? ['verify'] : ['sign'];
break;
default:
throw (0, _Utils.lazyDOMException)('The algorithm is not supported', 'NotSupportedError');
}
if ((0, _Utils.hasAnyNotIn)(usages, checkSet)) {
throw (0, _Utils.lazyDOMException)(`Unsupported key usage for a ${name} key`, 'SyntaxError');
}
}
function createECPublicKeyRaw(namedCurve, keyData) {
if (!namedCurve) {
throw new Error('Invalid namedCurve');
}
const handle = _NativeQuickCrypto.NativeQuickCrypto.webcrypto.createKeyObjectHandle();
if (!handle.initECRaw(_keys.kNamedCurveAliases[namedCurve], keyData)) {
console.log('keyData', (0, _Utils.ab2str)(keyData));
throw new Error('Invalid keyData 1');
}
return new _keys.PublicKeyObject(handle);
}
function ecExportKey(key, format) {
return _NativeQuickCrypto.NativeQuickCrypto.webcrypto.ecExportKey(format, key.keyObject.handle);
}
function ecImportKey(format, keyData, algorithm, extractable, keyUsages) {
const {
name,
namedCurve
} = algorithm;
// if (!ArrayPrototypeIncludes(ObjectKeys(kNamedCurveAliases), namedCurve)) {
// throw lazyDOMException('Unrecognized namedCurve', 'NotSupportedError');
// }
let keyObject;
// const usagesSet = new SafeSet(keyUsages);
switch (format) {
// case 'spki': {
// // verifyAcceptableEcKeyUse(name, true, usagesSet);
// try {
// keyObject = createPublicKey({
// key: keyData,
// format: 'der',
// type: 'spki',
// });
// } catch (err) {
// throw new Error(`Invalid keyData 2: ${err}`);
// }
// break;
// }
// case 'pkcs8': {
// // verifyAcceptableEcKeyUse(name, false, usagesSet);
// try {
// keyObject = createPrivateKey({
// key: keyData,
// format: 'der',
// type: 'pkcs8',
// });
// } catch (err) {
// throw new Error(`Invalid keyData 3 ${err}`);
// }
// break;
// }
case 'jwk':
{
const data = keyData;
if (!data.kty) throw (0, _Utils.lazyDOMException)('Invalid keyData 4', 'DataError');
if (data.kty !== 'EC') throw (0, _Utils.lazyDOMException)('Invalid JWK "kty" Parameter', 'DataError');
if (data.crv !== namedCurve) throw (0, _Utils.lazyDOMException)('JWK "crv" does not match the requested algorithm', 'DataError');
verifyAcceptableEcKeyUse(name, data.d === undefined, keyUsages);
if (keyUsages.length > 0 && data.use !== undefined) {
const checkUse = name === 'ECDH' ? 'enc' : 'sig';
if (data.use !== checkUse) throw (0, _Utils.lazyDOMException)('Invalid JWK "use" Parameter', 'DataError');
}
(0, _Utils.validateKeyOps)(data.key_ops, keyUsages);
if (data.ext !== undefined && data.ext === false && extractable === true) {
throw (0, _Utils.lazyDOMException)('JWK "ext" Parameter and extractable mismatch', 'DataError');
}
if (algorithm.name === 'ECDSA' && data.alg !== undefined) {
let algNamedCurve;
switch (data.alg) {
case 'ES256':
algNamedCurve = 'P-256';
break;
case 'ES384':
algNamedCurve = 'P-384';
break;
case 'ES512':
algNamedCurve = 'P-521';
break;
}
if (algNamedCurve !== namedCurve) throw (0, _Utils.lazyDOMException)('JWK "alg" does not match the requested algorithm', 'DataError');
}
const handle = _NativeQuickCrypto.NativeQuickCrypto.webcrypto.createKeyObjectHandle();
const type = handle.initJwk(data, namedCurve);
if (type === undefined) throw (0, _Utils.lazyDOMException)('Invalid JWK', 'DataError');
keyObject = type === _keys.KeyType.Private ? new _keys.PrivateKeyObject(handle) : new _keys.PublicKeyObject(handle);
break;
}
case 'raw':
{
const data = keyData;
verifyAcceptableEcKeyUse(name, true, keyUsages);
const buffer = typeof data === 'string' ? (0, _Utils.binaryLikeToArrayBuffer)(data) : (0, _Utils.bufferLikeToArrayBuffer)(data);
keyObject = createECPublicKeyRaw(namedCurve, buffer);
break;
}
default:
{
throw new Error(`Unknown EC import format: ${format}`);
}
}
switch (algorithm.name) {
case 'ECDSA':
// Fall through
case 'ECDH':
if (keyObject.asymmetricKeyType !== 'ec') throw new Error('Invalid key type');
break;
}
// if (!keyObject[kHandle].checkEcKeyData()) {
// throw new Error('Invalid keyData 5');
// }
// const { namedCurve: checkNamedCurve } = keyObject[kHandle].keyDetail({});
// if (kNamedCurveAliases[namedCurve] !== checkNamedCurve)
// throw new Error('Named curve mismatch');
return new _keys.CryptoKey(keyObject, {
name,
namedCurve
}, keyUsages, extractable);
}
const ecdsaSignVerify = (key, data, {
hash
}, signature) => {
const mode = signature === undefined ? _sig.SignMode.kSignJobModeSign : _sig.SignMode.kSignJobModeVerify;
const type = mode === _sig.SignMode.kSignJobModeSign ? 'private' : 'public';
if (key.type !== type) throw (0, _Utils.lazyDOMException)(`Key must be a ${type} key`, 'InvalidAccessError');
const hashname = (0, _Utils.normalizeHashName)(hash);
return _NativeQuickCrypto.NativeQuickCrypto.webcrypto.signVerify(mode, key.keyObject.handle,
// three undefined args because C++ uses `GetPublicOrPrivateKeyFromJs` & friends
undefined, undefined, undefined, (0, _Utils.bufferLikeToArrayBuffer)(data), hashname, undefined,
// salt length, not used with ECDSA
undefined,
// pss padding, not used with ECDSA
_sig.DSASigEnc.kSigEncP1363, (0, _Utils.bufferLikeToArrayBuffer)(signature || new ArrayBuffer(0)));
};
exports.ecdsaSignVerify = ecdsaSignVerify;
const ecGenerateKey = async (algorithm, extractable, keyUsages) => {
const {
name,
namedCurve
} = algorithm;
if (!Object.keys(_keys.kNamedCurveAliases).includes(namedCurve || '')) {
throw (0, _Utils.lazyDOMException)(`Unrecognized namedCurve '${namedCurve}'`, 'NotSupportedError');
}
// const usageSet = new SafeSet(keyUsages);
switch (name) {
case 'ECDSA':
if ((0, _Utils.hasAnyNotIn)(keyUsages, ['sign', 'verify'])) {
throw (0, _Utils.lazyDOMException)('Unsupported key usage for an ECDSA key', 'SyntaxError');
}
break;
case 'ECDH':
if ((0, _Utils.hasAnyNotIn)(keyUsages, ['deriveKey', 'deriveBits'])) {
throw (0, _Utils.lazyDOMException)('Unsupported key usage for an ECDH key', 'SyntaxError');
}
// Fall through
}
const options = {
namedCurve
};
const [err, keypair] = await (0, _Cipher.generateKeyPairPromise)('ec', options);
if (err) {
throw (0, _Utils.lazyDOMException)('ecGenerateKey (generateKeyPairPromise) failed', {
name: 'OperationError',
cause: err
});
}
let publicUsages = [];
let privateUsages = [];
switch (name) {
case 'ECDSA':
publicUsages = (0, _Utils.getUsagesUnion)(keyUsages, 'verify');
privateUsages = (0, _Utils.getUsagesUnion)(keyUsages, 'sign');
break;
case 'ECDH':
publicUsages = [];
privateUsages = (0, _Utils.getUsagesUnion)(keyUsages, 'deriveKey', 'deriveBits');
break;
}
const keyAlgorithm = {
name,
namedCurve
};
const pub = new _keys.PublicKeyObject(keypair?.publicKey);
const publicKey = new _keys.CryptoKey(pub, keyAlgorithm, publicUsages, true);
const priv = new _keys.PrivateKeyObject(keypair?.privateKey);
const privateKey = new _keys.CryptoKey(priv, keyAlgorithm, privateUsages, extractable);
return {
publicKey,
privateKey
};
};
exports.ecGenerateKey = ecGenerateKey;
//# sourceMappingURL=ec.js.map
;