js-libp2p-keychain
A secure key chain for libp2p in JavaScript
Features
- Manages the lifecycle of a key
- Keys are encrypted at rest
- Enforces the use of safe key names
- Uses encrypted PKCS 8 for key storage
- Uses PBKDF2 for a "stetched" key encryption key
- Enforces NIST SP 800-131A and NIST SP 800-132
- Uses PKCS 7: CMS (aka RFC 5652) to provide cryptographically protected messages
- Delays reporting errors to slow down brute force attacks
Table of Contents
Install
npm install --save libp2p-keychain
Usage
const Keychain = require('libp2p-keychain')
const FsStore = require('datastore-fs')
const datastore = new FsStore('./a-keystore')
const opts = {
passPhrase: 'some long easily remembered phrase'
}
const keychain = new Keychain(datastore, opts)
API
Managing a key
createKey (name, type, size, callback)
renameKey (oldName, newName, callback)
removeKey (name, callback)
exportKey (name, password, callback)
importKey (name, pem, password, callback)
importPeer (name, peer, callback)
A naming service for a key
listKeys (callback)
findKeyById (id, callback)
findKeyByName (name, callback)
Cryptographically protected messages
cms.createAnonymousEncryptedData (name, plain, callback)
cms.readData (cmsData, callback)
KeyInfo
The key management and naming service API all return a KeyInfo
object. The id
is a universally unique identifier for the key. The name
is local to the key chain.
{
name: 'rsa-key',
id: 'QmYWYSUZ4PV6MRFYpdtEDJBiGs4UrmE6g8wmAWSePekXVW'
}
The key id is the SHA-256 multihash of its public key. The public key is a protobuf encoding containing a type and the DER encoding of the PKCS SubjectPublicKeyInfo.
Private key storage
A private key is stored as an encrypted PKCS 8 structure in the PEM format. It is protected by a key generated from the key chain's passPhrase using PBKDF2. Its file extension is .p8
.
The default options for generating the derived encryption key are in the dek
object
const defaultOptions = {
createIfNeeded: true,
//See https://cryptosense.com/parameter-choice-for-pbkdf2/
dek: {
keyLength: 512 / 8,
iterationCount: 10000,
salt: 'you should override this value with a crypto secure random number',
hash: 'sha512'
}
}
Physical storage
The actual physical storage of an encrypted key is left to implementations of interface-datastore. A key benifit is that now the key chain can be used in browser with the js-datastore-level implementation.
Contribute
Feel free to join in. All welcome. Open an issue!
This repository falls under the IPFS Code of Conduct.