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.
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'; //
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
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.
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 = ...; // SPKI (public key) or PKCS8 (either encrypted or plaintext private key)const yourJasonWebKey = kty: 'EC' ... ;const yourOctetFormKey = 0x04 ... // only for Elliptic Curve Crypto Key.const keyObjFromPem = 'pem' yourStringPemKey;const keyObjFromDer = 'der' yourBinaryDerKey;const keyObjFromJwk = 'jwk' yourJasonWebKey;const keyObjFromOct = '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 = 'pem' encryptedPemKey;const yourPassphrase = '...';// first now you can check the statusconst isEncrypted = keyObjisEncrypted;// before using the key object, decrypt the key object with the passphrase.ifisEncrypted await keyObj;const thisMustBeFalse = keyObjisEncrypted; // false// you can lock the key object by encrypting it as well.if!thisMustBeFalse await keyObj;const thisMustBeTrue = keyObjisEncrypted; // true;
Exporting keys in desired format
From instantiated key objects, various types of keys can be exported.
const keyObj = 'pem' pemKey;// jwklet jwk;if!keyObjisEncrypted jwk = await keyObj;ifkeyObjisPrivate jwk = await keyObj; // export public key from private key.// pemlet pem;if!keyObjisEncrypted pem = await keyObj;ifkeyObjisPrivate pem = await keyObj; // export public key from private key.// Only ECC Key: export compressed form of public key from private/public key.pem = await keyObj;// derlet der;if!keyObjisEncrypted der = await keyObj;ifkeyObjisPrivate der = await keyObj; // export public key from private key.// Only ECC Keys: export compressed form of public key from private/public key.der = await keyObj;// Only ECC Keys// octet fromlet oct;if!keyObjisEncrypted oct = await keyObj;ifkeyObjisPrivate oct = await keyObj; // export public key from private key.// export compressed form of public key from private/public key.oct = await keyObj;
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 = 'pem' pemKey;// encrypt with default paramslet encryptedPem;if!keyObjisEncrypted && keyObjisPrivateencryptedPem = await keyObj;// encrypt with intended paramsif!keyObjisEncrypted && keyObjisPrivateencryptedPem = await keyObj;
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 = 'pem' pemKey;let thumbprint;// with default params (hash is SHA-256, output is in Uint8Array)if!keyObjisEncrypted thumbprint = await keyObj;// with intented paramsif!keyObjisEncrypted thumbprint = await keyObj;
Note that the thumbprint generated from a public key is exactly same as that from its paired private key.
Now this library supports the following curve for elliptic curve cryptography.
- P-256 (secp256r1)
- P-384 (secp384r1)
- P-521 (secp521r1)
- P-256K (secp256k1)
Licensed under the MIT license, see