Comparing version 3.8.0 to 4.0.0
# crypto-ld ChangeLog | ||
## 3.8.0 - 2020-06-23 | ||
## 4.0.0 - 2020-08-01 | ||
### Added | ||
- Setup CI and coverage workflow. | ||
- Add node 14 to CI. | ||
- Use sodium-native@3.2.0. | ||
### Changed | ||
- Implement chai-like `.use()` API for installing and specifying individual key | ||
types. | ||
- **BREAKING**: Extracted bundled Ed25519 and RSA key suites to their own | ||
libraries. | ||
- **BREAKING**: Remove deprecated `.owner` instance property | ||
- **BREAKING**: Remove deprecated `.passphrase` instance property, and the `encrypt()` and | ||
`decrypt()` methods (these are no longer used). | ||
- **BREAKING**: Remove deprecated/unused `publicKey` and `privateKey` properties. | ||
- **BREAKING**: Rename `.publicNode()` to `.export({publicKey: true})`. | ||
- **BREAKING**: `.export()` now requires explicitly stating whether you're | ||
exporting public or private key material. | ||
- **BREAKING**: Changed `verifyFingerprint()` to used named params. | ||
- **BREAKING**: Changed `addPublicKey()` and `addPrivateKey()` to used named params. | ||
### 4.0.0 - Purpose | ||
The previous design (`v3.7` and earlier) bundled two key types with this | ||
library (RSA and Ed25519), which resulted in extraneous code and bundle size | ||
for projects that only used one of them (or used some other suite). The | ||
decision was made to extract those bundled suites to their own repositories, | ||
and to add a builder-style `.use()` API to `crypto-ld` so that client code | ||
could select just the suites they needed. | ||
Since this was a comprehensive breaking change in usage, this also gave an | ||
opportunity to clean up and streamline the existing API, change function | ||
signatures to be consistent (for example, to consistently used named parameters), | ||
and to remove deprecated and unused APIs and properties. | ||
### Upgrading from v3.7.0 | ||
Since this is a comprehensive breaking change, you will need to audit and change | ||
pretty much all usage of `crypto-ld` and compatible key pairs. Specifically: | ||
* Ed25519 and RSA keys are no longer imported from `crypto-ld`, they'll need to | ||
be imported from their own packages. | ||
* Since key suites have been decoupled from `crypto-ld`, it means that this | ||
library should only be used when a project is using _multiple_ key suites. | ||
If you're just using a single suite, then you can use that suite directly, | ||
without `crypto-ld`. | ||
* Most function param signatures have been changed to use `{}` style named params. | ||
## 3.7.0 - 2019-09-06 | ||
@@ -11,0 +48,0 @@ |
/* | ||
* Copyright (c) 2018-2019 Digital Bazaar, Inc. All rights reserved. | ||
* Copyright (c) 2018-2020 Digital Bazaar, Inc. All rights reserved. | ||
*/ | ||
'use strict'; | ||
const {CryptoLD} = require('./CryptoLD'); | ||
const {LDKeyPair} = require('./LDKeyPair'); | ||
const {LDVerifierKeyPair} = require('./LDVerifierKeyPair'); | ||
module.exports = { | ||
Ed25519KeyPair: require('./Ed25519KeyPair'), | ||
LDKeyPair: require('./LDKeyPair'), | ||
RSAKeyPair: require('./RSAKeyPair'), | ||
CryptoLD, | ||
LDKeyPair, | ||
LDVerifierKeyPair | ||
}; | ||
/** | ||
* [JSON Web encryption]{@link https://tools.ietf.org/html/rfc7516} | ||
* @typedef {Object} JWE | ||
* @property {string} unprotected - A header for the jwe. | ||
* @property {string} iv - A base64 url. | ||
* @property {string} ciphertext - A base64 url. | ||
* @property {string} tag - A base64 url. | ||
*/ | ||
/** | ||
* PSS Object | ||
* @typedef {Object} PSS | ||
* @property encode {Function} | ||
* @property verify {Function} | ||
*/ | ||
/** | ||
* KeyPair Options. | ||
* @typedef {Object} KeyPairOptions | ||
* @property {string} passphrase - For encrypting the private key. | ||
* @property {string} id - Key Id. | ||
* @property {string} controller - | ||
* DID of the person/entity controlling this key. | ||
* @property {string} owner - DID or URI of owner. DEPRECATED, use | ||
* `controller` instead. | ||
*/ | ||
/** | ||
* Serialized LD Key. | ||
* @typedef {Object} SerializedLdKey | ||
* @property {Ed25519VerificationKey2018|RsaVerificationKey2018} | ||
* type - The Encryption type. | ||
* @property {string} passphrase - The passphrase to generate the pair. | ||
*/ |
/*! | ||
* Copyright (c) 2018-2019 Digital Bazaar, Inc. All rights reserved. | ||
* Copyright (c) 2018-2020 Digital Bazaar, Inc. All rights reserved. | ||
*/ | ||
'use strict'; | ||
const forge = require('node-forge'); | ||
const {util: {binary: {base58}}} = forge; | ||
/** | ||
* When adding support for a new suite type for `crypto-ld`, developers should | ||
* do the following: | ||
* | ||
* 1. Create their own npm package / github repo, such as `example-key-pair`. | ||
* 2. Subclass either LDVerifierKeyPair (for signature-related suites), or | ||
* LDKeyPair (for all other types, such as key-agreement-related). | ||
* 3. Add to the key type table in the `crypto-ld` README.md (that's this repo). | ||
*/ | ||
class LDKeyPair { | ||
/** | ||
* Note: Actual key material | ||
* (like `publicKeyBase58` for Ed25519 or | ||
* `publicKeyPem` for RSA) is handled in the subclass. | ||
* An LDKeyPair can encrypt private key material. | ||
* @classdesc The Abstract Base Class on which KeyPairs are based. | ||
* @example | ||
* // LDKeyPair is an Abstract Class and should only | ||
* // be used as a base class for other KeyPairs. | ||
* @param {KeyPairOptions} [options={}] - | ||
* See [KeyPairOptions]{@link ./index.md#KeyPairOptions}. | ||
* @param {string} [options.passphrase=null] - For encrypting the private key. | ||
* @param {string} options.id - The Key id. | ||
* @param {string} options.controller - DID of the person/entity controlling | ||
* this key. | ||
* @param {string} [options.owner] - DID or URI of owner. DEPRECATED, use | ||
* `controller` instead. | ||
* Creates a public/private key pair instance. This is an abstract base class, | ||
* actual key material and suite-specific methods are handled in the subclass. | ||
* | ||
* To generate or import a key pair, use the `cryptoLd` instance. | ||
* @see CryptoLD.js | ||
* | ||
* @param {string} id - The Key id, typically composed of controller | ||
* URL and key fingerprint as hash fragment. | ||
* @param {string} controller - DID/URL of the person/entity | ||
* controlling this key. | ||
*/ | ||
constructor(options = {}) { | ||
this.passphrase = options.passphrase || null; | ||
this.id = options.id; | ||
this.controller = options.controller; | ||
this.owner = options.owner; | ||
constructor({id, controller} = {}) { | ||
this.id = id; | ||
this.controller = controller; | ||
// this.type is set in subclass constructor | ||
// this.publicKey* and this.privateKey* is handled in sub-classes | ||
} | ||
/** | ||
* @abstract | ||
* @interface | ||
* @readonly | ||
* Returns the public key. | ||
* @throws If not implemented by the subclass. | ||
* Generates a new public/private key pair instance. | ||
* Note that this method is not typically called directly by client code, | ||
* but instead is used through a `cryptoLd` instance. | ||
* | ||
* @returns {string} A public key. | ||
*/ | ||
get publicKey() { | ||
throw new Error('Abstract method, must be implemented in subclass.'); | ||
} | ||
/** | ||
* @abstract | ||
* @interface | ||
* @readonly | ||
* Returns the private key. | ||
* @throws If not implemented by the subclass. | ||
* @param {object} options - Suite-specific options for the KeyPair. For | ||
* common options, see the `LDKeyPair.constructor()` docstring. | ||
* | ||
* @returns {string} A private key. | ||
* @returns {Promise<LDKeyPair>} An LDKeyPair instance. | ||
*/ | ||
get privateKey() { | ||
static async generate(/* options */) { | ||
throw new Error('Abstract method, must be implemented in subclass.'); | ||
} | ||
/** | ||
* Generates an LdKeyPair using SerializedLdKey options. | ||
* @param {SerializedLdKey} options - Options for generating the KeyPair. | ||
* @example | ||
* > const options = { | ||
* type: 'RsaVerificationKey2018', | ||
* passphrase: 'Test1234' | ||
* }; | ||
* > const keyPair = await LDKeyPair.generate(options); | ||
* | ||
* @returns {Promise<LDKeyPair>} An LDKeyPair. | ||
* @throws Unsupported Key Type. | ||
* @see [SerializedLdKey]{@link ./index.md#SerializedLdKey} | ||
*/ | ||
static async generate(options) { | ||
switch(options.type) { | ||
case 'Ed25519VerificationKey2018': | ||
const Ed25519KeyPair = require('./Ed25519KeyPair'); | ||
return Ed25519KeyPair.generate(options); | ||
case 'RsaVerificationKey2018': | ||
const RSAKeyPair = require('./RSAKeyPair'); | ||
return RSAKeyPair.generate(options); | ||
default: | ||
throw new Error(`Unsupported Key Type: ${options.type}`); | ||
} | ||
} | ||
/** | ||
* Generates a KeyPair from some options. | ||
* @param {SerializedLdKey} options - Will generate a key pair | ||
* @param {object} options - Will generate a key pair | ||
* in multiple different formats. | ||
* @see [SerializedLdKey]{@link ./index.md#SerializedLdKey} | ||
* @example | ||
* > const options = { | ||
* type: 'Ed25519VerificationKey2018', | ||
* passphrase: 'Test1234' | ||
* type: 'Ed25519VerificationKey2018' | ||
* }; | ||
@@ -104,106 +61,86 @@ * > const edKeyPair = await LDKeyPair.from(options); | ||
*/ | ||
static async from(options) { | ||
switch(options.type) { | ||
case 'Ed25519VerificationKey2018': | ||
const Ed25519KeyPair = require('./Ed25519KeyPair'); | ||
return Ed25519KeyPair.from(options); | ||
case 'RsaVerificationKey2018': | ||
const RSAKeyPair = require('./RSAKeyPair'); | ||
return RSAKeyPair.from(options); | ||
default: | ||
throw new Error(`Unsupported Key Type: ${options.type}`); | ||
} | ||
static async from(/* options */) { | ||
throw new Error('Abstract method, must be implemented in subclass.'); | ||
} | ||
/** | ||
* Creates an instance of LDKeyPair from a key fingerprint. | ||
* Note: Only key types that use their full public key in the fingerprint | ||
* are supported (so, currently, only 'ed25519'). | ||
* Exports the serialized representation of the KeyPair | ||
* and other information that json-ld Signatures can use to form a proof. | ||
* | ||
* @param {string} fingerprint | ||
* @returns {LDKeyPair} | ||
* @throws Unsupported Fingerprint Type. | ||
* @param {boolean} [publicKey] - Export public key material? | ||
* @param {boolean} [privateKey] - Export private key material? | ||
* | ||
* @returns {object} A public key object | ||
* information used in verification methods by signatures. | ||
*/ | ||
static fromFingerprint({fingerprint}) { | ||
// skip leading `z` that indicates base58 encoding | ||
const buffer = base58.decode(fingerprint.substr(1)); | ||
// buffer is: 0xed 0x01 <public key bytes> | ||
if(buffer[0] === 0xed && buffer[1] === 0x01) { | ||
const Ed25519KeyPair = require('./Ed25519KeyPair'); | ||
return new Ed25519KeyPair({ | ||
publicKeyBase58: base58.encode(buffer.slice(2)) | ||
}); | ||
export({publicKey = false, privateKey = false} = {}) { | ||
if(!publicKey && !privateKey) { | ||
throw new Error( | ||
'Export requires specifying either "publicKey" or "privateKey".'); | ||
} | ||
const key = { | ||
id: this.id, | ||
type: this.type, | ||
controller: this.controller | ||
}; | ||
if(publicKey) { | ||
this.addPublicKey({key}); // Subclass-specific | ||
} | ||
if(privateKey) { | ||
this.addPrivateKey({key}); // Subclass-specific | ||
} | ||
return key; | ||
} | ||
throw new Error(`Unsupported Fingerprint Type: ${fingerprint}`); | ||
/** | ||
* Adds the suite-specific public key material, serialized to string, to | ||
* the exported public key node. | ||
* @param {object} key - Public key object. | ||
* @returns {object} | ||
*/ | ||
addPublicKey(/* {key} */) { | ||
throw new Error('Abstract method, must be implemented in subclass.'); | ||
} | ||
/** | ||
* Generates a | ||
* [pdkdf2]{@link https://en.wikipedia.org/wiki/PBKDF2} key. | ||
* @param {string} password - The password for the key. | ||
* @param {string} salt - Noise used to randomize the key. | ||
* @param {number} iterations - The number of times to run the algorithm. | ||
* @param {number} keySize - The byte length of the key. | ||
* @example | ||
* > const key = await LdKeyPair.pbkdf2('Test1234', salt, 10, 32); | ||
* Adds the suite-specific private key material, serialized to string, to | ||
* the exported public key node. | ||
* | ||
* @returns {Promise<Object>} A promise that resolves to a pdkdf2 key. | ||
* @see https://github.com/digitalbazaar/forge#pkcs5 | ||
* @param {object} key - Private key object. | ||
* @returns {object} | ||
*/ | ||
static async pbkdf2(password, salt, iterations, keySize) { | ||
return new Promise((resolve, reject) => { | ||
forge.pkcs5.pbkdf2(password, salt, iterations, keySize, (err, key) => | ||
err ? reject(err) : resolve(key)); | ||
}); | ||
addPrivateKey(/* {key} */) { | ||
throw new Error('Abstract method, must be implemented in subclass.'); | ||
} | ||
/** | ||
* Contains the encryption type & public key for the KeyPair | ||
* and other information that json-ld Signatures can use to form a proof. | ||
* @param {Object} [options={}] - Needs either a controller or owner. | ||
* @param {string} [options.controller=this.controller] - DID of the | ||
* person/entity controlling this key pair. | ||
* @param {string} [options.owner=this.owner] - DID of key owner. | ||
* Deprecated term, use `controller`. | ||
* @example | ||
* > ldKeyPair.publicNode(); | ||
* {id: 'test-keypair-id', owner: 'did:uuid:example'} | ||
* Returns the public key fingerprint, multibase+multicodec encoded. The | ||
* specific fingerprint method is determined by the key suite, and is often | ||
* either a hash of the public key material (such as with RSA), or the | ||
* full encoded public key (for key types with sufficiently short | ||
* representations, such as ed25519). | ||
* This is frequently used in initializing the key id, or generating some | ||
* types of cryptonym DIDs. | ||
* | ||
* @returns {Object} A public node with | ||
* information used in verification methods by signatures. | ||
* @returns {string} | ||
*/ | ||
publicNode({controller = this.controller, owner = this.owner} = {}) { | ||
const publicNode = { | ||
id: this.id, | ||
type: this.type, | ||
}; | ||
if(controller) { | ||
publicNode.controller = controller; | ||
} | ||
if(owner) { | ||
publicNode.owner = owner; | ||
} | ||
this.addEncodedPublicKey(publicNode); // Subclass-specific | ||
return publicNode; | ||
fingerprint() { | ||
throw new Error('Abstract method, must be implemented in subclass.'); | ||
} | ||
// publicKeyPem, publicKeyJwk, publicKeyHex, publicKeyBase64, publicKeyBase58 | ||
/** | ||
* Exports the publicNode with an encrypted private key attached. | ||
* @example | ||
* > const withPrivateKey = await edKeyPair.export(); | ||
* Verifies that a given key fingerprint matches the public key material | ||
* belonging to this key pair. | ||
* | ||
* @returns {KeyPairOptions} A public node with encrypted private key. | ||
* @see [KeyPairOptions]{@link ./index.md#KeyPairOptions} | ||
* @param {string} fingerprint - Public key fingerprint. | ||
* | ||
* @returns {{verified: boolean}} | ||
*/ | ||
async export() { | ||
const keyNode = this.publicNode(); | ||
return this.addEncryptedPrivateKey(keyNode); // Subclass-specific | ||
verifyFingerprint(/* {fingerprint} */) { | ||
throw new Error('Abstract method, must be implemented in subclass.'); | ||
} | ||
} | ||
module.exports = LDKeyPair; | ||
module.exports = { | ||
LDKeyPair | ||
}; |
{ | ||
"name": "crypto-ld", | ||
"version": "3.8.0", | ||
"description": "A library for managing cryptographic keys using Linked Data.", | ||
"version": "4.0.0", | ||
"description": "A Javascript library for generating and performing common operations on Linked Data cryptographic key pairs.", | ||
"homepage": "https://github.com/digitalbazaar/crypto-ld", | ||
@@ -24,8 +24,3 @@ "author": { | ||
], | ||
"dependencies": { | ||
"base64url-universal": "^1.0.1", | ||
"bs58": "^4.0.1", | ||
"node-forge": "~0.9.0", | ||
"semver": "^6.2.0" | ||
}, | ||
"dependencies": {}, | ||
"optionalDependencies": { | ||
@@ -35,35 +30,25 @@ "sodium-native": "^3.2.0" | ||
"devDependencies": { | ||
"@babel/core": "^7.2.2", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.3.1", | ||
"@babel/plugin-transform-modules-commonjs": "^7.2.0", | ||
"@babel/plugin-transform-runtime": "^7.2.0", | ||
"@babel/preset-env": "^7.3.1", | ||
"@babel/runtime": "^7.3.1", | ||
"babel-loader": "^8.0.5", | ||
"benchmark": "^2.1.4", | ||
"chai": "^4.1.2", | ||
"core-js": "^2.6.3", | ||
"cross-env": "^5.1.3", | ||
"eslint": "^6.8.0", | ||
"eslint-config-digitalbazaar": "^2.0.0", | ||
"jsdoc-to-markdown": "^4.0.1", | ||
"karma": "^4.0.1", | ||
"karma-babel-preprocessor": "^8.0.0", | ||
"karma-chrome-launcher": "^2.2.0", | ||
"karma-edge-launcher": "^0.4.2", | ||
"karma-firefox-launcher": "^1.1.0", | ||
"karma-ie-launcher": "^1.0.0", | ||
"karma-mocha": "^1.3.0", | ||
"@babel/core": "^7.10.2", | ||
"@babel/plugin-transform-modules-commonjs": "^7.10.1", | ||
"@babel/plugin-transform-runtime": "^7.10.1", | ||
"@babel/preset-env": "^7.10.2", | ||
"@babel/runtime": "^7.10.2", | ||
"babel-loader": "^8.1.0", | ||
"chai": "^4.2.0", | ||
"cross-env": "^7.0.2", | ||
"eslint": "^7.2.0", | ||
"eslint-config-digitalbazaar": "^2.5.0", | ||
"eslint-plugin-jsdoc": "^27.0.4", | ||
"karma": "^5.0.9", | ||
"karma-babel-preprocessor": "^8.0.1", | ||
"karma-chai": "^0.1.0", | ||
"karma-chrome-launcher": "^3.1.0", | ||
"karma-mocha": "^2.0.1", | ||
"karma-mocha-reporter": "^2.2.5", | ||
"karma-safari-launcher": "^1.0.0", | ||
"karma-sourcemap-loader": "^0.3.7", | ||
"karma-tap-reporter": "0.0.6", | ||
"karma-webpack": "^3.0.5", | ||
"mocha": "^6.0.0", | ||
"karma-webpack": "^4.0.2", | ||
"mocha": "^7.2.0", | ||
"mocha-lcov-reporter": "^1.3.0", | ||
"multibase": "^0.6.0", | ||
"multicodec": "^0.5.0", | ||
"multihashes": "^0.4.14", | ||
"nyc": "^15.0.0", | ||
"webpack": "^4.29.0" | ||
"nyc": "^15.1.0", | ||
"webpack": "^4.43.0" | ||
}, | ||
@@ -79,11 +64,2 @@ "nyc": { | ||
}, | ||
"browser": { | ||
"bs58": false, | ||
"crypto": false, | ||
"sodium-native": false, | ||
"util": false, | ||
"semver": false, | ||
"./lib/ed25519PublicKeyNode12.js": false, | ||
"./lib/ed25519PrivateKeyNode12.js": false | ||
}, | ||
"engines": { | ||
@@ -100,5 +76,5 @@ "node": ">=8.3.0" | ||
"scripts": { | ||
"test": "npm run test-node", | ||
"test-node": "cross-env NODE_ENV=test mocha --preserve-symlinks -t 30000 -A -R ${REPORTER:-spec} tests/*.spec.js", | ||
"test-karma": "karma start", | ||
"test": "npm run lint && npm run test-node && npm run test-karma", | ||
"test-node": "cross-env NODE_ENV=test mocha --preserve-symlinks -t 30000 -A -R ${REPORTER:-spec} tests/**/*.spec.js", | ||
"test-karma": "karma start tests/karma.conf.js", | ||
"benchmark": "node benchmark/benchmark.js", | ||
@@ -108,5 +84,4 @@ "coverage": "cross-env NODE_ENV=test nyc --reporter=lcov --reporter=text-summary npm run test-node", | ||
"coverage-report": "nyc report", | ||
"lint": "eslint lib tests", | ||
"generate-docs": "node docs/generate.js" | ||
"lint": "eslint lib tests" | ||
} | ||
} |
214
README.md
@@ -1,6 +0,6 @@ | ||
# Crypto LD (Linked Data) _(crypto-ld)_ | ||
# Cryptographic Key Pair Library for Linked Data _(crypto-ld)_ | ||
[![Build Status](https://travis-ci.org/digitalbazaar/crypto-ld.png?branch=master)](https://travis-ci.org/digitalbazaar/crypto-ld) | ||
[![Node.js CI](https://github.com/digitalbazaar/crypto-ld/workflows/Node.js%20CI/badge.svg)](https://github.com/digitalbazaar/crypto-ld/actions?query=workflow%3A%22Node.js+CI%22) | ||
> A Javascript library for cryptographic operations using Linked Data | ||
> A Javascript library for generating and performing common operations on Linked Data cryptographic key pairs. | ||
@@ -13,3 +13,2 @@ ## Table of Contents | ||
- [Usage](#usage) | ||
- [API](#api-documentation) | ||
- [Contribute](#contribute) | ||
@@ -21,58 +20,40 @@ - [Commercial Support](#commercial-support) | ||
See also (related specs): | ||
### Supported Key Types | ||
* [Linked Data Proofs 1.0](https://w3c-dvcg.github.io/ld-proofs/) | ||
* [Linked Data Cryptographic Suite Registry](https://w3c-ccg.github.io/ld-cryptosuite-registry/) | ||
This library provides general Linked Data cryptographic key generation | ||
functionality, but does not support any individual key type by default. | ||
As a developer, in order to use this library, you will need to make the | ||
following decisions, constrained by your use case: | ||
To use it, you must [install individual driver libraries](#usage) for each | ||
cryptographic key type. The following libraries are currently supported. | ||
1. [Which key type](#choosing-key-type) and suite to use? | ||
2. What IDs will you give your keys? We recommend the following pattern: | ||
`<did or url>#<key fingerprint>`. (See Exporting Key Pair section below | ||
for an example of this.) | ||
3. (Not required, but highly recommended) What is your [Private Key Storage](#private-key-storage) | ||
strategy? (KMS, file system, secure wallet) | ||
| Type | Crypto Suite | Library | Usage | | ||
|-------------|--------------|---------|-------| | ||
| `Ed25519` | [Ed25519VerificationKey2018](https://w3c-ccg.github.io/ld-cryptosuite-registry/#ed25519) | [`ed25519-verification-key-2018`](https://github.com/digitalbazaar/ed25519-verification-key-2018) | Signatures, VCs, zCaps, DIDAuth | | ||
| `Secp256k1` | [EcdsaSecp256k1VerificationKey2019](https://w3c-ccg.github.io/ld-cryptosuite-registry/#secp256k1) | [`ecdsa-secp256k1-verification-key-2019`](https://github.com/digitalbazaar/ecdsa-secp256k1-verification-key-2019) | Signatures, VCs, zCaps, DIDAuth, HD Wallets | | ||
| `RSA` | [RsaVerificationKey2018](https://w3c-ccg.github.io/ld-cryptosuite-registry/#rsasignature2018) | [`rsa-verification-key-2018`](https://github.com/digitalbazaar/rsa-verification-key-2018) | Signatures, VCs | | ||
| `X25519/Curve25519` | X25519KeyAgreementKey2019 | [`x25519-key-agreement-key-2019`](https://github.com/digitalbazaar/x25519-key-agreement-key-2019) | [ECDH](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman) key agreement, JWE/CWE encryption with [`minimal-cipher`](https://github.com/digitalbazaar/minimal-cipher) | | ||
### Supported Key Types | ||
See also (related specs): | ||
This library supports the following key types (used primarily for the purpose | ||
of digital signatures): | ||
* [Linked Data Cryptographic Suite Registry](https://w3c-ccg.github.io/ld-cryptosuite-registry/) | ||
* [Linked Data Proofs 1.0](https://w3c-ccg.github.io/ld-proofs/) | ||
* [Ed25519](https://w3c-ccg.github.io/ld-cryptosuite-registry/#ed25519) | ||
* [RSA](https://w3c-ccg.github.io/ld-cryptosuite-registry/#rsa) | ||
#### Choosing a Key Type | ||
These key pairs can be used for general purpose digital signatures using the | ||
For digital signatures using the | ||
[`jsonld-signatures`](https://github.com/digitalbazaar/jsonld-signatures), | ||
signing of Verifiable Credentials using [`vc-js`](https://github.com/digitalbazaar/vc-js), | ||
and other purposes. | ||
authorization capabilities, and DIDAuth operations: | ||
Additional key types are available (using the same API as this library) at the | ||
following repos: | ||
* Prefer **Ed25519VerificationKey2018** type keys, by default. | ||
* Use **EcdsaSepc256k1** keys if your use case requires it (for example, if | ||
you're developing for a Bitcoin-based or Ethereum-based ledger), or if you | ||
require Hierarchical Deterministic (HD) wallet functionality. | ||
* Only use RSA keys when interfacing with systems that require them. | ||
For key agreement protocols for encryption operations: | ||
* [EcdsaSecp256k1](https://w3c-dvcg.github.io/lds-ecdsa-secp256k1-2019/) at | ||
[`secp256k1-key-pair`](https://github.com/digitalbazaar/secp256k1-key-pair/) | ||
* Curve25519 at [`x25519-key-pair`](https://github.com/digitalbazaar/x25519-key-pair) | ||
(for use with [`minimal-cipher`](https://github.com/digitalbazaar/minimal-cipher)) | ||
* Use **Curve25519** with the [`minimal-cipher`](https://github.com/digitalbazaar/minimal-cipher) | ||
library. | ||
#### Choosing Key Type | ||
TODO: Add design considerations for choosing key types / cryptographic | ||
algorithms for various purposes. For now: | ||
* Use **Ed25519** keys if you can | ||
* Use **EcdsaSepc256k1** keys if you must (for example, if you're developing for | ||
a Bitcoin-based or Ethereum-based ledger) | ||
* You _can_ use RSA keys to sign, if your use case requires it. | ||
* Use **Curve25519** for key agreement protocols. | ||
#### Private Key Storage | ||
Where to store the private keys? | ||
TODO: Add a brief discussion of where to store the private keys. Point to | ||
several recommended Wallet or KMS libraries. | ||
Use `await keyPair.export()` | ||
## Security | ||
@@ -85,4 +66,3 @@ | ||
- Node.js 8.3+ required. | ||
- Node.js 10.12.0+ is highly recommended due to RSA key generation speed. | ||
- Node.js 10.12.0+ is required. | ||
@@ -99,68 +79,140 @@ To install locally (for development): | ||
### Generating a new key pair | ||
### Installing Support for Key Types | ||
Ed25519: | ||
In order to use this library, you will need to import and install driver | ||
libraries for key types you'll be working with via the `use()` method. | ||
To use the library with one or more supported suites: | ||
```js | ||
const {Ed25519KeyPair} = require('crypto-ld'); | ||
import {Ed25519VerificationKey2018} from 'ed25519-verification-key-2018'; | ||
import {RsaVerificationKey2018} from 'rsa-verification-key-2018'; | ||
import {EcdsaSecp256k1VerificationKey2019} from 'ecdsa-secp256k1-verification-key-2019'; | ||
import {X25519KeyAgreementKey2019} from 'x25519-key-agreement-key-2019'; | ||
const keyPair = await Ed25519KeyPair.generate(); | ||
import {CryptoLD} from 'crypto-ld'; | ||
const cryptoLd = new CryptoLD(); | ||
cryptoLd.use(Ed25519VerificationKey2018); | ||
cryptoLd.use(RsaVerificationKey2018); | ||
cryptoLd.use(EcdsaSecp256k1VerificationKey2019); | ||
cryptoLd.use(X25519KeyAgreementKey2019); | ||
const edKeyPair = await cryptoLd.generate({type: 'Ed25519VerificationKey2018'}); | ||
const rsaKeyPair = await cryptoLd.generate({type: 'RsaVerificationKey2018'}); | ||
``` | ||
RSA: | ||
### Generating a new public/private key pair | ||
To generate a new public/private key pair: `cryptoLd.generate(options)`: | ||
* `{string} [type]` Suite name, required. | ||
* `{string} [controller]` Optional controller URI or DID to initialize the | ||
generated key. (This will also init the key id.) | ||
* `{string} [seed]` Optional deterministic seed value (only supported by some | ||
key types, such as `ed25519`) from which to generate the key. | ||
### Importing a key pair from storage | ||
To create an instance of a public/private key pair from data imported from | ||
storage, use `cryptoLd.from()`: | ||
```js | ||
const {RSAKeyPair} = require('crypto-ld'); | ||
const serializedKeyPair = { ... }; | ||
const keyPair = await RSAKeyPair.generate(); | ||
const keyPair = await cryptoLd.from(serializedKeyPair); | ||
``` | ||
### Exporting a public/private key pair | ||
Note that only installed key types are supported, if you try to create a | ||
key pair via `from()` for an unsupported type, an error will be thrown. | ||
### Common individual key pair operations | ||
The full range of operations will depend on key type. Here are some common | ||
operations supported by all key types. | ||
#### Exporting the public key only | ||
To export just the public key of a pair - use `export()`: | ||
```js | ||
const edKeyPair = await Ed25519KeyPair.generate(); | ||
edKeyPair.id = 'did:ex:123#' + edKeyPair.fingerprint(); | ||
console.log(await edKeyPair.export()) | ||
/* -> | ||
await keyPair.export({publicKey: true}); | ||
// -> | ||
{ | ||
id: 'did:ex:123#z6MkumafR1duPR5FZgbVu8nzX3VyhULoXNpq9rpjhfaiMQmx', | ||
controller: 'did:ex:123', | ||
type: 'Ed25519VerificationKey2018', | ||
publicKeyBase58: 'GKKcpmPU3sanTBkoDZq9fwwysu4x7VaUTquosPchSBza', | ||
privateKeyBase58: | ||
'3cEzNVGdLoujfhWXqrbo1FgYy9GHA5GXYvB4KixHVuQoRbWbHTJP7XTkj6LqXeiFhw79v85E4wjPQc8WcdyzntcA' | ||
publicKeyBase58: 'GKKcpmPU3sanTBkoDZq9fwwysu4x7VaUTquosPchSBza' | ||
} | ||
*/ | ||
``` | ||
#### Exporting the full public-private key pair | ||
To export the full key pair, including private key (warning: this should be a | ||
carefully considered operation, best left to dedicated Key Management Systems): | ||
```js | ||
await keyPair.export({publicKey: true, privateKey: true}); | ||
// -> | ||
{ | ||
id: 'did:ex:123#z6Mks8wJbzhWdmkQZgw7z2qHwaxPVnFsFmEZSXzGkLkvhMvL', | ||
controller: 'did:ex:123', | ||
type: 'Ed25519VerificationKey2018', | ||
publicKeyBase58: 'DggG1kT5JEFwTC6RJTsT6VQPgCz1qszCkX5Lv4nun98x', | ||
privateKeyBase58: 'sSicNq6YBSzafzYDAcuduRmdHtnrZRJ7CbvjzdQhC45ewwvQeuqbM2dNwS9RCf6buUJGu6N3rBy6oLSpMwha8tc' | ||
} | ||
``` | ||
### Importing a key pair from storage | ||
#### Generating and verifying key fingerprint | ||
If you know what type of key you're expecting, use its appropriate class: | ||
To generate a fingerprint: | ||
```js | ||
const serializedKeyPair = JSON.stringify(await keyPair.export()); | ||
// later | ||
const keyPair = await Ed25519KeyPair.from(JSON.parse(serializedKeyPair)); | ||
keyPair.fingerprint(); | ||
// -> | ||
'z6Mks8wJbzhWdmkQZgw7z2qHwaxPVnFsFmEZSXzGkLkvhMvL' | ||
``` | ||
If you do not know which key type to expect, `LDKeyPair.from()` will route | ||
based on type: | ||
To verify a fingerprint: | ||
```js | ||
const {LDKeyPair} = require('crypto-ld'); | ||
keyPair.verifyFingerprint({ | ||
fingerprint: 'z6Mks8wJbzhWdmkQZgw7z2qHwaxPVnFsFmEZSXzGkLkvhMvL' | ||
}); | ||
// -> | ||
{ valid: true } | ||
``` | ||
// serializedKeyPair contains a serialized Ed25519KeyPair | ||
const keyPair = await LDKeyPair.from(JSON.parse(serializedKeyPair)); | ||
### Operations on signature-related key pairs | ||
For key pairs that are related to signature and verification (that extend from | ||
the `LDVerifierKeyPair` class), two additional operations must be supported: | ||
#### Creating a signer function | ||
In order to perform a cryptographic signature, you need to create a `sign` | ||
function, and then invoke it. | ||
```js | ||
const keyPair = cryptoLd.generate({type: 'Ed25519VerificationKey2018'}); | ||
const {sign} = keyPair.signer(); | ||
const data = 'test data to sign'; | ||
const signatureValue = await sign({data}); | ||
``` | ||
## API Documentation | ||
#### Creating a verifier function | ||
See [LD Key Pair Documentation](/docs/LDKeyPair.md) | ||
In order to verify a cryptographic signature, you need to create a `verify` | ||
function, and then invoke it (passing it the data to verify, and the signature). | ||
See [Ed25519 Key Pair Documentation](/docs/Ed25519KeyPair.md) | ||
```js | ||
const keyPair = cryptoLd.generate({type: 'Ed25519VerificationKey2018'}); | ||
See [RSA Key Pair Documentation](/docs/RSAKeyPair.md) | ||
const {verify} = keyPair.verifier(); | ||
See [Type Documentation](/docs/index.md) | ||
const {valid} = await verify({data, signature}); | ||
``` | ||
@@ -167,0 +219,0 @@ ## Contribute |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1
23
232
26565
8
272
1
- Removedbase64url-universal@^1.0.1
- Removedbs58@^4.0.1
- Removednode-forge@~0.9.0
- Removedsemver@^6.2.0
- Removedbase-x@3.0.10(transitive)
- Removedbase64url@3.0.1(transitive)
- Removedbase64url-universal@1.1.0(transitive)
- Removedbs58@4.0.1(transitive)
- Removednode-forge@0.9.2(transitive)
- Removedsafe-buffer@5.2.1(transitive)
- Removedsemver@6.3.1(transitive)