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

js-crypto-key-utils

v1.0.7

Published

Universal Module for Cryptographic Key Utilities in JavaScript, including PEM-JWK converters

Downloads

54,399

Readme

Universal Module for Cryptographic Key Utilities in JavaScript

npm version License: MIT

WARNING: At this time this solution should be considered suitable for research and experimentation, further code and security review is needed before utilization in a production application.

Introduction and Overview

This library is designed to 'universally' provide several functions for a cryptographic key handling, which means it works both on most browsers and on Node.js just by importing from npm/source code. This key utility library provides converters for EC/RSA keys in PEM/DER<->JWK, octet form of EC keys <-> JWK, and computation of JWK thumbprints. Especially for the conversion PEM/DER <->JWK, encryption and decryption of private key in DER/PEM are supported.

Installation

At your project directory, do either one of the following.

  • From npm/yarn:
    $ npm install --save js-crypto-key-utils // npm
    $ yarn add js-crypto-key-utils // yarn
  • From GitHub:
    $ git clone https://github.com/junkurihara/jscu.git
    $ cd js-crypto-utils/packages/js-crypto-key-utils
    & yarn build

Then you should import the package as follows.

import keyutil from 'js-crypto-key-utils'; // for npm
import keyutil from 'path/to/js-crypto-key-utils/dist/index.js'; // for github

The bundled file is also given as js-crypto-key-utils/dist/jsckey.bundle.js for a use case where the module is imported as a window.jsckey object via script tags.

Usage

Supported key types are Json Web Key (JWK, RFC7517), and PEM/DER. Octet-Formatted Key (SECG SEC1 2.3.3 and 2.3.4, link to PDF) is also available for elliptic curve cryptography keys. Note that for PEM/DER, public keys are encoded to the form of SubjectPublicKeyInfo (SPKI) defined as a part of X.509 public key certificate (RFC5280). The detailed encoding rule for elliptic curve cryptographic keys is given in RFC5480. On the other hand, private keys are encoded to hte form of PrivateKeyInfo defined in PKCS#8 (RFC5958). The detailed encoding rule for elliptic curve cryptographic keys is given in RFC5915 as well as SPKI. Please refer to RFC3447 for the detailed encoding rule of RSA public and private keys.

Instantiation

At first, you need to instantiate Key object by importing various type of keys.

const yourStringPemKey = '------BEGIN PRIVATE...'; // SPKI (public key) or PKCS8 (either encrypted or plaintext private key)
const yourBinaryDerKey = new Uint8Array([...]); // SPKI (public key) or PKCS8 (either encrypted or plaintext private key)
const yourJasonWebKey = {kty: 'EC', ... };
const yourOctetFormKey = new Uint8Array([0x04, ...]) // only for Elliptic Curve Crypto Key.

const keyObjFromPem = new keyutil.Key('pem', yourStringPemKey);
const keyObjFromDer = new keyutil.Key('der', yourBinaryDerKey);
const keyObjFromJwk = new keyutil.Key('jwk', yourJasonWebKey);
const keyObjFromOct = new keyutil.Key('oct', yourOctetFormKey, {namedCurve: '...'}); //namedCurve like 'P-256K' is required.

Handling key objects

In a case where the imported key is encrypted (pem/der), it needs to be decrypted before getting exported.

const keyObj = new keyutil.Key('pem', encryptedPemKey);
const yourPassphrase = '...';

// first now you can check the status
const isEncrypted = keyObj.isEncrypted;

// before using the key object, decrypt the key object with the passphrase.
if(isEncrypted) await keyObj.decrypt(yourPassphrase);

const thisMustBeFalse = keyObj.isEncrypted; // false

// you can lock the key object by encrypting it as well.
if(!thisMustBeFalse) await keyObj.encrypt(yourPassphrase);

const thisMustBeTrue = keyObj.isEncrypted; // true;

Exporting keys in desired format

From instantiated key objects, various types of keys can be exported.

const keyObj = new keyutil.Key('pem', pemKey);

// jwk
let jwk;
if(!keyObj.isEncrypted) jwk = await keyObj.export('jwk');
if(keyObj.isPrivate) jwk = await keyObj.export('jwk', {outputPublic: true}); // export public key from private key.

// pem
let pem;
if(!keyObj.isEncrypted) pem = await keyObj.export('pem');
if(keyObj.isPrivate) pem = await keyObj.export('pem', {outputPublic: true}); // export public key from private key.
// Only ECC Key: export compressed form of public key from private/public key.
pem = await keyObj.export('pem', {outputPublic: true, compact: true});

// der
let der;
if(!keyObj.isEncrypted) der = await keyObj.export('der');
if(keyObj.isPrivate) der = await keyObj.export('der', {outputPublic: true}); // export public key from private key.
// Only ECC Keys: export compressed form of public key from private/public key.
der = await keyObj.export('der', {outputPublic: true, compact: true});

// Only ECC Keys
// octet from
let oct;
if(!keyObj.isEncrypted) oct = await keyObj.export('oct');
if(keyObj.isPrivate) oct = await keyObj.export('oct', {outputPublic: true}); // export public key from private key.
// export compressed form of public key from private/public key.
oct = await keyObj.export('oct', {outputPublic: true, compact: true});

Exporting encrypted keys with arbitrary specified passphrase.

All you need to export encrypted private keys in PEM/DER is just putting passphrase in the API. The default encryption algorithm follows PKCS#5 v2.1 (RFC8018) and uses AES256-CBC and HMAC-with-SHA-256 to encrypt your private key.

const keyObj = new keyutil.Key('pem', pemKey);

// encrypt with default params
let encryptedPem;
if(!keyObj.isEncrypted && keyObj.isPrivate)
  encryptedPem = await keyObj.export('pem', {encryptParams: {passphrase: 'top secret'}});

// encrypt with intended params
if(!keyObj.isEncrypted && keyObj.isPrivate)
  encryptedPem = await keyObj.export('pem', {
    encryptParams: {
      passphrase: 'top secret',
      algorithm: 'pbes2', // default. 'pbeWith...' is also available, i.e., pbes1.
      cipher: 'aes256-cbc', // default. for encryption. 'aes128-cbc', 'aes192-cbc'(only node), 'des-ede3-cbc' are available as well.
      prf: 'hmacWithSHA256' // default. for key derivation
    }
  });

Getting JWK Thumbprint

You can obtain the JWK Thumbprint defined in RFC7638 from instantiated key object. The API can be invoked as follows.

const keyObj = new keyutil.Key('pem', pemKey);

let thumbprint;

// with default params (hash is SHA-256, output is in Uint8Array)
if(!keyObj.isEncrypted) thumbprint = await keyObj.getJwkThumbprint();

// with intented params
if(!keyObj.isEncrypted) thumbprint = await keyObj.getJwkThumbprint(
  'SHA-512',
  'hex' // output is hex string
);

Note that the thumbprint generated from a public key is exactly same as that from its paired private key.

Note

Now this library supports the following curve for elliptic curve cryptography.

  • P-256 (secp256r1)
  • P-384 (secp384r1)
  • P-521 (secp521r1)
  • P-256K (secp256k1)

License

Licensed under the MIT license, see LICENSE file.