npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@douganderson444/crypto-key-composer

v0.1.5

Published

A library to decompose and compose crypto keys of different types and formats

Downloads

11

Readme

crypto-key-composer

NPM version Downloads Build Status Coverage Status Dependency status Dev Dependency status

A library to decompose and compose crypto keys of different types and formats.

Installation

$ npm install crypto-key-composer

This library is written in modern JavaScript and is published in both CommonJS and ES module transpiled variants. If you target older browsers please make sure to transpile accordingly. Moreover, some of this library's dependencies use the native Node Buffer module. This means that you must compile your app through a bundler that automatically injects a Buffer compatible implementation for the browser, such as Webpack.

API

decomposePrivateKey(inputKey, [options])

Parses a private key, extracting information containing its format, keyAlgorithm, keyData and encryptionAlgorithm.

import { decomposePrivateKey } from 'crypto-key-composer';

const myPrivatePemKey = `
-----BEGIN RSA PRIVATE KEY-----
ACTUAL KEY BASE64 HERE
-----END RSA PRIVATE KEY-----
`

const myPrivateDecomposedKey = decomposePrivateKey(myPrivatePemKey)
// {
//     format: 'pkcs1-pem',
//     keyAlgorithm: {
//         id: 'rsa-encryption'
//     },
//     keyData: {
//         modulus: Uint8Array(...),
//         publicExponent: Uint8Array(...),
//         privateExponent: Uint8Array(...),
//         // ...
//     },
//     encryptionAlgorithm: null
// }

The inputKey may be a TypedArray (including Node's Buffer), an ArrayBuffer or a binary string.

⚠️ Do not use the keyAlgorithm.id to identify the key type. The reason is that several identifiers map to the same key type. As an example, rsa-encryption, sha512-with-rsa-encryption, rsa-oaep and rsassa-pss are all RSA keys. Instead, use getKeyTypeFromAlgorithm to properly get the key type.

Available options:

| name | type | default | description | | ---- | ---- | ------- | ----------- | | format | string/Array | ['raw-pem', 'pkcs8-pem'] | Limit the parsing to one or more formats | | password | string | | The password to use to decrypt the key |

Meaningful errors with codes are thrown if something went wrong. When options.format is an array, this function will attempt to decompose the key for the specified formats, in order and one by one. It will succeed if the key is using one of the formats or fail if it's using another format, throwing an AggregatedError containing a errors property with the errors indexed by format.

composePrivateKey(decomposedKey, [options])

Composes a private key from its parts: format, keyAlgorithm, keyData and encryptionAlgorithm. This function is the inverse of decomposePrivateKey.

import { composePrivateKey } from 'crypto-key-composer';

const myPrivatePemKey = composePrivateKey({
    format: 'pkcs1-pem',
    keyAlgorithm: {
        id: 'rsa-encryption',
    },
    keyData: {
        modulus: Uint8Array(...),
        publicExponent: Uint8Array(...),
        privateExponent: Uint8Array(...),
        // ...
    }
});

The return value depends on the format. PEM based formats return a regular string while DER based formats return a Uint8Array.

Available options:

| name | type | default | description | | ---- | ---- | ------- | ----------- | | password | string | | The password to use to encrypt the key |

Meaningful errors with codes are thrown if something went wrong.

decomposePublicKey(inputKey, [options])

Parses a public key, extracting information containing its format, keyAlgorithm and keyData.

import { decomposePublicKey } from 'crypto-key-composer';

const myPublicPemKey = `
-----BEGIN PUBLIC KEY-----
ACTUAL KEY BASE64 HERE
-----END PUBLIC KEY-----
`

const myDecomposedPublicKey = decomposePublicKey(myPublicPemKey)
// {
//     format: 'spki-pem',
//     keyAlgorithm: {
//         id: 'rsa-encryption'
//     },
//     keyData: {
//        modulus: Uint8Array(...),
//        publicExponent: Uint8Array(...)
//     },
//     encryptionAlgorithm: null
// }

The inputKey may be a TypedArray (including Node's Buffer), an ArrayBuffer or a binary string.

⚠️ Do not use the keyAlgorithm.id to identify the key type. The reason is that several identifiers map to the same key type. As an example, rsa-encryption, rsaes-oaep and rsassa-pss are all RSA keys. Instead, use getKeyTypeFromAlgorithm to properly get the key type.

Available options:

| name | type | default | description | | ---- | ---- | ------- | ----------- | | format | string/Array | ['raw-pem', 'spki-pem'] | Limit the parsing to one or more formats |

Meaningful errors with codes are thrown if something went wrong. When options.format is an array, this function will attempt to decompose the key for the specified formats, in order and one by one. It will succeed if the key is using one of the formats or fail if it's using another format, throwing an AggregatedError containing a errors property with the errors indexed by format.

composePublicKey(decomposedKey)

Composes a public key from its parts: format, keyAlgorithm and keyData. This function is the inverse of decomposePublicKey.

import { composePublicKey } from 'crypto-key-composer';

const myPublicPemKey = composePublicKey({
    format: 'spki-pem',
    keyAlgorithm: {
        id: 'rsa-encryption',
    },
    keyData: {
        modulus: Uint8Array(...),
        publicExponent: Uint8Array(...)
    }
});

The return value depends on the format. PEM based formats return a regular string while DER based formats return a Uint8Array.

Meaningful errors with codes are thrown if something went wrong.

getKeyTypeFromAlgorithm(keyAlgorithm)

Returns the key type based on the passed key algorithm. The keyAlgorithm might be an object or a string.

import { getKeyTypeFromAlgorithm } from 'crypto-key-composer';

getKeyTypeFromAlgorithm({ id: 'rsa-encryption' })  // rsa
getKeyTypeFromAlgorithm('rsa-encryption')  // rsa
getKeyTypeFromAlgorithm('ed25519')  // ed25519

Supported formats and algorithms

Formats

Below you will find the list of supported formats for private and public keys.

The raw-der is the DER encoded ASN1 format defined in RFC 8017 for RSA keys and in RFC5915 for EC keys.

Supported public key algorithms:

  • Just the standard rsa-encryption RSA algorithm (or the rsa alias)

Supported private key algorithms:

  • Just the standard rsa-encryption RSA algorithm (or the rsa alias)
  • Just the standard ec-public-key EC algorithm (or the ec alias)

Supported encryption algorithms: none

⚠️ It's recommended to use the newer PKCS8 & SPKI formats for private and public keys respectively because they are able to store more types of keys. Moreover, PKCS8 keys may be encrypted.

The raw-pem is the PEM encoded version of raw-der and is defined in RFC 1421.

Supported public key algorithms:

  • Just the standard rsa-encryption RSA algorithm (or the rsa alias)

Supported private key algorithms:

  • Just the standard rsa-encryption RSA algorithm (or the rsa alias)
  • Just the standard ec-public-key RSA algorithm (or the ec alias)

Supported encryption algorithms:

  • keyDerivationFunc: openssl-derive-bytes (default)
  • encryptionScheme: aes256-cbc (default), aes192-cbc, aes128-cbc, des-ede3-cbc, des-cbc, rc2-cbc

⚠️ It's recommended to use the newer PKCS8 & SPKI formats for private and public keys respectively because they are able to store more types of keys. Moreover, PKCS8 keys have stronger encryption.

The pkcs1-der is the DER encoded ASN1 format defined in RFC 8017. It's a subset of the raw-der format, supporting only RSA keys.

Supported private key algorithms:

  • Just the standard rsa-encryption RSA algorithm (or the rsa alias)

Supported encryption algorithms: none

⚠️ It's recommended to use the newer PKCS8 format for private keys because it's able to store more types of keys and support encryption.

The pkcs1-pem is the PEM encoded version of pkcs1-der and is defined in RFC 1421. It's a subset of the raw-pem format, supporting only RSA keys.

Supported private key algorithms:

  • Just the standard rsa-encryption RSA algorithm (or the rsa alias)

Supported encryption algorithms:

  • keyDerivationFunc: openssl-derive-bytes (default)
  • encryptionScheme: aes256-cbc (default), aes192-cbc, aes128-cbc, des-ede3-cbc, des-cbc, rc2-cbc

⚠️ It's recommended to use the newer PKCS8 format for private keys because it's able to store more types of keys and support stronger encryption algorithms.

The pkcs8-der is the DER encoded ASN1 format defined in RFC 5208 and RFC 5985.

Supported private key algorithms:

  • RSA keys
  • EC keys
  • ED25519 keys

Supported encryption algorithms (PKCS#5):

  • keyDerivationFunc: pbkdf2 (default)
  • encryptionScheme: aes256-cbc (default), aes192-cbc, aes128-cbc, des-ede3-cbc, des-cbc, rc2-cbc

The pkcs8-pem is the PEM encoded version of pkcs8-der and is defined in RFC 1421.

Supported private key algorithms:

  • RSA keys
  • EC keys
  • ED25519 keys

Supported encryption algorithms (PKCS#5):

  • keyDerivationFunc: pbkdf2 (default)
  • encryptionScheme: aes256-cbc (default), aes192-cbc, aes128-cbc, des-ede3-cbc, des-cbc, rc2-cbc

The spki-der is a format to represent various types of public keys and is defined in RFC 5280.

Supported public key algorithms:

  • RSA keys
  • EC keys
  • ED25519 keys

Supported encryption algorithms: does not apply

The spki-pem is the PEM encoded version of spki-der and is defined in RFC 1421.

Supported public key algorithms:

  • RSA keys
  • EC keys
  • ED25519 keys

Supported encryption algorithms: does not apply

Key Algorithms

Below you will find the list of supported key algorithms. Because the actual supported key algorithms vary from format to format, be sure to also check the Formats section.

The following RSA key algorithms are supported:

  • rsa-encryption
  • md2-with-rsa-encryption
  • md4-with-rsa-encryption
  • md5-with-rsa-encryption
  • sha1-with-rsa-encryption
  • sha224-with-rsa-encryption
  • sha256-with-rsa-encryption
  • sha384-with-rsa-encryption
  • sha512-with-rsa-encryption
  • sha512-224-with-rsa-encryption
  • sha512-256-with-rsa-encryption

⚠️ At the moment, rsaes-oaep and rsassa-pss are not yet supported (see issue #4).

All of them are expressed like so:

{
    keyAlgorithm: {
        id: 'rsa-encryption'
    }
}

Because they have no parameters, the example above may also be expressed like so:

{
    keyAlgorithm: 'rsa-encryption'
}

You may use the rsa alias in the key algorithm id, which maps to rsa-encryption.

The following EC (elliptic curve) algorithms are supported:

  • ec-public-key
  • ec-dh
  • ec-mqv

Only named curves may be used. The following curves are supported:

  • sect163k1
  • sect163r1
  • sect239k1
  • sect113r1
  • sect113r2
  • secp112r1
  • secp112r2
  • secp160r1
  • secp160k1
  • secp256k1
  • sect163r2
  • sect283k1
  • sect283r1
  • sect131r1
  • sect131r2
  • sect193r1
  • sect193r2
  • sect233k1
  • sect233r1
  • secp128r1
  • secp128r2
  • secp160r2
  • secp192k1
  • secp224k1
  • secp224r1
  • secp384r1
  • secp521r1
  • sect409k1
  • sect409r1
  • sect571k1
  • sect571r1
  • secp192r1
  • secp256r1

The combination of the key algorithm and the named curve are expressed like so:

{
    keyAlgorithm: {
        id: 'ec-public-key',
        namedCurve: 'secp256k1',
    }
}

You may use the ec alias in the key algorithm id, which maps to ec-public-key.

ED25519 keys just have a single algorithm, ed25519, and may be expressed like so:

{
    keyAlgorithm: {
        id: 'ed25519'
    }
}

Because there are no parameters, the example above may also be expressed like so:

{
    keyAlgorithm: 'ed25519'
}

Key Data

The key data is the interpreted key contents. Below, you will find the key data structure for each key type.

{
    keyData: {
        modulus: Uint8Array(/* ... */),
        publicExponent: Uint8Array(/* ... */),
        privateExponent: Uint8Array(/* ... */),
        prime1: Uint8Array(/* ... */),
        prime2: Uint8Array(/* ... */),
        exponent1: Uint8Array(/* ... */),
        exponent2: Uint8Array(/* ... */),
        coefficient: Uint8Array(/* ... */),
        // Only defined if number of primes is greater than 2
        otherPrimeInfos: [
            {
                prime: Uint8Array(/* ... */),
                exponent: Uint8Array(/* ... */),
                coefficient Uint8Array(/* ... */)
            }
        ]
    }
}
{
    keyData: {
        modulus: Uint8Array(/* ... */),
        publicExponent: Uint8Array(/* ... */)
    }
}
{
    keyData: {
        d: Uint8Array(/* ... */),
        x: Uint8Array(/* ... */),
        y: Uint8Array(/* ... */),
    }
}
{
    keyData: {
        x: Uint8Array(/* ... */),
        y: Uint8Array(/* ... */),
    }
}
{
    keyData: {
        seed: Uint8Array( /* 32 bytes */)
    }
}

The seed is composed of 32 bytes which serves as the basis to derive the 64 bytes private key and the 32 bytes public key. This closely follows what is defined in RFC 8032.

{
    keyData: {
        bytes: Uint8Array( /* 32 bytes */)
    }
}

Encryption Algorithms

The encryption algorithm only apply for private keys and is composed by two parts: Key Derivation Function and the Encryption Scheme. Below you will find the supported algorithms for these parts. Because the actual supported encryption algorithms vary from format to format, be sure to also check the Formats section.

Key Derivation Function

The openssl-derive-bytes is used when encrypting PKCS#1 PEM keys and was pionereed by OpenSSL to derive a key from the password.

{
    encryptionAlgorithm: {
        keyDerivationFunc: {
            id: 'openssl-derive-bytes',
        }
        encryptionScheme: ...
    }
}

Because there are no parameters, the example above may also be expressed like so:

{
    encryptionAlgorithm: {
        keyDerivationFunc: 'openssl-derive-bytes',
        encryptionScheme: ...
    }
}

The pbkdf2 is used when encrypting PKCS#8 keys and is part of PKCS#5 defined by RFC 8018.

{
    encryptionAlgorithm: {
        keyDerivationFunc: {
            id: 'pbkdf2',
            iterationCount: 10000,  // The number of iterations
            keyLength: 32, // Automatic, based on the `encryptionScheme`
            prf: 'hmac-with-sha512'  // The pseudo-random function
        }
        encryptionScheme: ...
    }
}

The parameters above are the default ones and may be omited if you don't need to tweak them. In that case, you may express the example above like so:

{
    encryptionAlgorithm: {
        keyDerivationFunc: 'pbkdf2',
        encryptionScheme: ...
    }
}

The supported prf values are hmac-with-sha512 (default), hmac-with-sha384, hmac-with-sha256 and hmac-with-sha1.

Encryption Scheme

The supported AES algorithms are aes256-cbc, aes192-cbc and aes128-cbc. Here's an example:

{
    encryptionAlgorithm: {
        keyDerivationFunc: ...,
        encryptionScheme: {
            id: 'aes256-cbc',
            iv: Uint8Array(/* random bytes */)
        }
    }
}

The parameters may be omited if you don't need to tweak them. In that case, you may express the example above like so:

{
    encryptionAlgorithm: {
        keyDerivationFunc: ...,
        encryptionScheme: 'aes256-cbc'
    }
}

The supported DES algorithms are des-cbc and des-ede3-cbc (triple DES). Here's an example:

{
    encryptionAlgorithm: {
        keyDerivationFunc: ...,
        encryptionScheme: {
            id: 'des-ede3-cbc',
            iv: Uint8Array(/* random bytes */)
        }
    }
}

The parameters may be omited if you don't need to tweak them. In that case, you may express the example above like so:

{
    encryptionAlgorithm: {
        keyDerivationFunc: ...,
        encryptionScheme: 'aes256-cbc'
    }
}

The supported RC2 algorithm is just rc2-cbc with 128 (default), 64 or 40 bits. Here's an example:

{
    encryptionAlgorithm: {
        keyDerivationFunc: ...,
        encryptionScheme: {
            id: 'rc2-cbc',
            iv: Uint8Array(/* random bytes */),
            bits: 128
        }
    }
}

The parameters may be omited if you don't need to tweak them. In that case, you may express the example above like so:

{
    encryptionAlgorithm: {
        keyDerivationFunc: ...,
        encryptionScheme: 'rc2-cbc'
    }
}

Tests

$ npm test
$ npm test -- --watch # during development

License

Released under the MIT License.