# js-crypto-key-utils

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

Latest version **1.0.7** (published 2023-09-27) · MIT license · 0 weekly downloads

## Install

```sh
npm install js-crypto-key-utils
pnpm add js-crypto-key-utils
yarn add js-crypto-key-utils
bun add js-crypto-key-utils
```

## Health

**Score 40/100 (D)** — status: abandoned.

Positive: has types; no vulnerabilities; high maintenance score; high quality score.

Warnings: low downloads; no esm support.

Negative: abandoned.

## Facts

| | |
|---|---|
| Version | 1.0.7 |
| Published | 2023-09-27 |
| First published | 2018-10-01 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 10 |
| Unpacked size | 408.1 KB |
| Known vulnerabilities | 0 (+3 in 1 direct dependencies) |
| Install scripts | no |
| GitHub stars | 162 |
| Author | Jun Kurihara |
| Maintainers | kurihara |
| Keywords | crypto, webcrypto, pem, der, jwk, spki, pkcs8, asn1, ecc, rsa, jwk thumbprint, rfc3447, rfc5280, rfc5208, rfc5480, rfc5915, rfc5958, rfc7638, rfc8018 |

## Links

- npm: https://www.npmjs.com/package/js-crypto-key-utils
- Repository: https://github.com/junkurihara/jscu
- Homepage: https://github.com/junkurihara/jscu/tree/master/packages/js-crypto-key-utils#readme
- Issues: https://github.com/junkurihara/jscu/issues
- npm.io page: https://npm.io/package/js-crypto-key-utils

## Dependencies (10)

- [buffer](https://npm.io/package/buffer.md) ~6.0.0
- [des.js](https://npm.io/package/des.js.md) ~1.1.0
- [asn1.js](https://npm.io/package/asn1.js.md) ~5.4.1
- [elliptic](https://npm.io/package/elliptic.md) ~6.5.0
- [js-crypto-aes](https://npm.io/package/js-crypto-aes.md) ^1.0.6
- [js-crypto-hash](https://npm.io/package/js-crypto-hash.md) ^1.0.7
- [js-crypto-pbkdf](https://npm.io/package/js-crypto-pbkdf.md) ^1.0.7
- [js-crypto-random](https://npm.io/package/js-crypto-random.md) ^1.0.5
- [lodash.clonedeep](https://npm.io/package/lodash.clonedeep.md) ~4.5.0
- [js-encoding-utils](https://npm.io/package/js-encoding-utils.md) 0.7.3

## Alternatives

- [@gemini-wallet/core](https://npm.io/package/@gemini-wallet/core.md) — 515.6K weekly downloads
- [utility](https://npm.io/package/utility.md) — 416.6K weekly downloads
- [@primno/dpapi](https://npm.io/package/@primno/dpapi.md) — 7.2K weekly downloads
- [pi-readseek](https://npm.io/package/pi-readseek.md) — 3.7K weekly downloads
- [@emilia-protocol/verify](https://npm.io/package/@emilia-protocol/verify.md) — 1.1K weekly downloads

## Recent versions

- 1.0.7 (latest) — 2023-09-27
- 1.0.6 — 2023-09-02
- 1.0.5 — 2023-08-25
- 1.0.4 — 2022-02-04
- 1.0.3 — 2021-11-22
- 1.0.2 — 2021-03-13
- 1.0.1 — 2021-03-13
- 1.0.0 — 2020-09-30
- 0.7.3 — 2020-01-14
- 0.7.2 — 2019-12-08
- 0.7.1 — 2019-11-19
- 0.7.0 — 2019-11-19
- 0.6.11 — 2019-09-05
- 0.6.10 — 2019-09-05
- 0.6.9 — 2019-08-14
- … 39 more at https://npm.io/package/js-crypto-key-utils/versions

## README

Universal Module for Cryptographic Key Utilities in JavaScript
--
[![npm version](https://badge.fury.io/js/js-crypto-key-utils.svg)](https://badge.fury.io/js/js-crypto-key-utils)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/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:
  ```shell
  $ npm install --save js-crypto-key-utils // npm
  $ yarn add js-crypto-key-utils // yarn
  ```
- From GitHub:
  ```shell
  $ 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.

```shell
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](https://tools.ietf.org/html/rfc7517)), and PEM/DER. Octet-Formatted Key ([SECG SEC1](http://www.secg.org/sec1-v2.pdf) 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](https://tools.ietf.org/html/rfc5280)). The detailed encoding rule for elliptic curve cryptographic keys is given in [RFC5480](https://tools.ietf.org/html/rfc5480). On the other hand, private keys are encoded to hte form of `PrivateKeyInfo` defined in PKCS#8 ([RFC5958](https://tools.ietf.org/html/rfc5958)). The detailed encoding rule for elliptic curve cryptographic keys is given in [RFC5915](https://tools.ietf.org/html/rfc5915) as well as SPKI. Please refer to [RFC3447](https://tools.ietf.org/html/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.

```javascript
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.
```javascript
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.
```javascript
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](https://tools.ietf.org/html/rfc8018)) and uses AES256-CBC and HMAC-with-SHA-256 to encrypt your private key.
```javascript
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](https://tools.ietf.org/html/rfc7638) from instantiated key object. The API can be invoked as follows.
```javascript
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.

---
_Source: https://npm.io/package/js-crypto-key-utils · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
