junkurihara/jscu

View on GitHub
packages/js-crypto-key-utils/src/util.ts

Summary

Maintainability
C
7 hrs
Test Coverage
/**
* util.js
*/
 
import jseu from 'js-encoding-utils';
import * as params from './params';
import {KeyStructure} from './asn1def';
import {AsnFormat, CurveTypes, DER, OctetEC, PEM, PublicOrPrivate} from './typedef';
 
/**
* Check if the given key is encrypted.
* @param {DER|PEM} key - Private key object in ASN.1 encoding.
* @param {AsnFormat} [format='pem'] - pem or der
* @return {boolean} - True if encrypted.
*/
Similar blocks of code found in 2 locations. Consider refactoring.
export const isAsn1Encrypted = (key: DER|PEM, format: AsnFormat = 'pem') => {
let keyType;
try{ keyType = getAsn1KeyType(key, format);} catch(e) {return false;}
return keyType === 'encryptedPrivate';
};
 
/**
* Check if the given key is public.
* @param {DER|PEM} key - Public key object in ASN.1 encoding.
* @param {AsnFormat} format - pem or der
* @return {boolean} - True if public.
*/
Similar blocks of code found in 2 locations. Consider refactoring.
export const isAsn1Public = (key: DER|PEM, format: AsnFormat = 'pem') => {
let keyType;
try{ keyType = getAsn1KeyType(key, format);} catch(e) {return false;}
return (keyType === 'public');
};
 
/**
* Retrieve the key type of public or private in ASN.1 format
* @param {DER|PEM} key - Key object in ASN.1 encoding.
* @param {AsnFormat} format - pem or der
* @return {'public'|'private'|'encryptedPrivate'} - The key type of the given key.
* @throws {Error} - Throws if NotSpkiNorPkcs8Key.
*/
export const getAsn1KeyType = (key: DER|PEM, format: AsnFormat = 'pem') => {
// Peel the pem strings
const binKey = (format === 'pem') ? jseu.formatter.pemToBin(<PEM>key) : key;
 
const decoded = KeyStructure.decode(Buffer.from(<Uint8Array>binKey), 'der');
if (decoded.type === 'encryptedPrivateKeyInfo') return 'encryptedPrivate';
else if (decoded.type === 'oneAsymmetricKey') return 'private';
else if (decoded.type === 'subjectPublicKeyInfo') return 'public';
else throw new Error('NotSpkiNorPkcs8Key');
};
 
/**
* Retrieve the type of SEC1 octet key.
* @param {OctetEC} sec1key - Key object in OctetEC encoding of Uint8Array.
* @param {CurveTypes} namedCurve - Name of elliptic curve like 'P-256'.
* @return {PublicOrPrivate} - public or private
* @throws {Error} - Throws if UnsupportedKeyStructure.
*/
Function `getSec1KeyType` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
export const getSec1KeyType = (sec1key: OctetEC, namedCurve: CurveTypes): PublicOrPrivate => {
const len = params.namedCurves[namedCurve].payloadSize;
 
const binKey = (sec1key instanceof Uint8Array) ? sec1key : jseu.encoder.hexStringToArrayBuffer(sec1key);
 
// original key type
if (binKey.length <= len) return 'private';
else if (
(binKey.length === 2*len+1 && binKey[0] === 0x04)
|| (binKey.length === len+1 && (binKey[0] === 0x02 || binKey[0] === 0x03))
) return 'public';
else throw new Error('UnsupportedKeyStructure');
};
 
/**
* Check key type of JWK.
* @param {JsonWebKey} jwkey - Key object in JWK format.
* @return {PublicOrPrivate} - public or private
* @throws {Error} - Throws if InvalidECKey, InvalidRSAKey or UnsupportedJWKType.
*/
Function `getJwkType` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.
export const getJwkType = (jwkey: JsonWebKey): PublicOrPrivate => {
if(jwkey.kty === 'EC'){
if (jwkey.x && jwkey.y && jwkey.d) return 'private';
else if (jwkey.x && jwkey.y) return 'public';
else throw new Error('InvalidECKey');
}
else if (jwkey.kty === 'RSA'){
Consider simplifying this complex logical expression.
if (jwkey.n && jwkey.e && jwkey.d && jwkey.p && jwkey.q && jwkey.dp && jwkey.dq && jwkey.qi) return 'private';
else if (jwkey.n && jwkey.e) return 'public';
else throw new Error('InvalidRSAKey');
}
else throw new Error('UnsupportedJWKType');
};
 
/**
* Prune leading zeros of an octet sequence in Uint8Array for jwk formatting of RSA.
* https://tools.ietf.org/html/rfc7518#section-6.3
* @param {Uint8Array} array - The octet sequence.
* @return {Uint8Array} - An octet sequence pruned leading zeros of length equal to or shorter than the input array.
* @throws {Error} - Throws if NonUint8Array.
*/
export const pruneLeadingZeros = (array: Uint8Array): Uint8Array => {
let offset = 0;
for (let i = 0; i < array.length; i++){
if(array[i] !== 0x00) break;
offset++;
}
 
const returnArray = new Uint8Array(array.length - offset);
returnArray.set(array.slice(offset, array.length));
return returnArray;
};
 
// for pem/oct/der formatting from jwk of RSA
/**
* Append leading zeros and generate an octet sequence of fixed length.
* @param {Uint8Array} array - An octet sequence.
* @param {Number} len - Intended length of output sequence.
* @returns {Uint8Array} - An octet sequence with leading zeros.
* @throws {Error} - Throws if NonUint8Array or InvalidLength.
*/
export const appendLeadingZeros = (array: Uint8Array, len: number): Uint8Array => {
if(array.length > len) throw new Error('InvalidLength');
 
const returnArray = new Uint8Array(len); // initialized with zeros
returnArray.set(array, len - array.length);
return returnArray;
};