line_push/node_modules/js-crypto-key-utils/README.md
2022-07-21 03:28:35 +00:00

158 lines
7.5 KiB
Markdown

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)
[![Dependencies](https://david-dm.org/junkurihara/jscu.svg?path=packages/js-crypto-key-utils)](https://david-dm.org/junkurihara/jscu?path=packages/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.