crypto-key-composer
Version:
A library to decompose and compose crypto keys of different types and formats
134 lines (109 loc) • 3.52 kB
JavaScript
import { maybeDecryptPemBody, maybeEncryptPemBody } from './encryption';
import { decomposeRawPrivateKey, composeRawPrivateKey, decomposeRawPublicKey, composeRawPublicKey } from './keys';
import { uint8ArrayToBinaryString, binaryStringToUint8Array } from '../../util/binary';
import { decodePem, encodePem } from '../../util/pem-encoder';
import { DecodePemFailedError, UnsupportedAlgorithmError } from '../../util/errors';
import { KEY_TYPES } from '../../util/key-types';
const getKeyType = pemType => {
const match = /^(\S+?) (PUBLIC|PRIVATE) KEY$/.exec(pemType);
return match && match[1].toLocaleLowerCase();
};
const getPemType = keyAlgorithm => {
const keyType = KEY_TYPES[keyAlgorithm.id];
return keyType && keyType.toUpperCase();
};
export const decomposePrivateKey = (pem, options) => {
let decodedPem;
try {
decodedPem = decodePem(pem, '* PRIVATE KEY');
} catch (err) {
err.invalidInputKey = err instanceof DecodePemFailedError;
throw err;
} // Decrypt pem if encrypted
const {
pemBody,
encryptionAlgorithm
} = maybeDecryptPemBody(decodedPem, options.password); // Extract the key type from it
const keyType = getKeyType(decodedPem.type);
/* istanbul ignore if */
if (!keyType) {
throw new DecodePemFailedError('Unable to extract key type from PEM', {
invalidInputKey: true
});
} // Finally decompose the key within it
const {
keyAlgorithm,
keyData
} = decomposeRawPrivateKey(keyType, pemBody);
return {
format: 'raw-pem',
keyAlgorithm,
keyData,
encryptionAlgorithm
};
};
export const composePrivateKey = ({
keyAlgorithm,
keyData,
encryptionAlgorithm
}, options) => {
// Compose the key
const rawKey = composeRawPrivateKey(keyAlgorithm, keyData); // Extract the pem type
const pemKeyType = getPemType(keyAlgorithm);
/* istanbul ignore if */
if (!pemKeyType) {
throw new UnsupportedAlgorithmError('Unable to extract pem type from key algorithm');
} // Encrypt pem if password was specified
const {
pemBody,
pemHeaders
} = maybeEncryptPemBody(rawKey, encryptionAlgorithm, options.password); // Finally build pem
return encodePem({
type: `${pemKeyType} PRIVATE KEY`,
body: uint8ArrayToBinaryString(pemBody),
...pemHeaders
});
};
export const decomposePublicKey = pem => {
// Decode pem
let decodedPem;
try {
decodedPem = decodePem(pem);
} catch (err) {
err.invalidInputKey = err instanceof DecodePemFailedError;
throw err;
} // Extract the key type from it
const keyType = getKeyType(decodedPem.type);
/* istanbul ignore if */
if (!keyType) {
throw new DecodePemFailedError('Unable to extract key type from PEM', {
invalidInputKey: true
});
} // Finally decompose the key within it
const pemBody = binaryStringToUint8Array(decodedPem.body);
const {
keyAlgorithm,
keyData
} = decomposeRawPublicKey(keyType, pemBody);
return {
format: 'raw-pem',
keyAlgorithm,
keyData
};
};
export const composePublicKey = ({
keyAlgorithm,
keyData
}) => {
// Compose the key
const rawKey = composeRawPublicKey(keyAlgorithm, keyData); // Extract the pem type
const pemKeyType = getPemType(keyAlgorithm);
/* istanbul ignore if */
if (!pemKeyType) {
throw new UnsupportedAlgorithmError('Unable to extract pem type from key algorithm');
} // Finally build pem
return encodePem({
type: `${pemKeyType} PUBLIC KEY`,
body: uint8ArrayToBinaryString(rawKey)
});
};