Skip to content

Commit

Permalink
feat: keychain in libp2p
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos committed May 7, 2020
1 parent b1a2b8a commit 1df9134
Show file tree
Hide file tree
Showing 11 changed files with 828 additions and 473 deletions.
2 changes: 1 addition & 1 deletion .aegir.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const after = async () => {
}

module.exports = {
bundlesize: { maxSize: '185kB' },
bundlesize: { maxSize: '200kB' },
hooks: {
pre: before,
post: after
Expand Down
286 changes: 285 additions & 1 deletion doc/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@
* [`connectionManager.get`](#connectionmanagerget)
* [`connectionManager.setPeerValue`](#connectionmanagersetpeervalue)
* [`connectionManager.size`](#connectionmanagersize)
* [`keychain.createKey`](#keychaincreatekey)
* [`keychain.renameKey`](#keychainrenamekey)
* [`keychain.removeKey`](#keychainremovekey)
* [`keychain.exportKey`](#keychainexportkey)
* [`keychain.importKey`](#keychainimportkey)
* [`keychain.importPeer`](#keychainimportpeer)
* [`keychain.list`](#keychainlist)
* [`keychain.findById`](#keychainfindbyid)
* [`keychain.findByName`](#keychainfindbyname)
* [`keychain.cms.encrypt`](#keychaincmsencrypt)
* [`keychain.cms.decrypt`](#keychaincmsdecrypt)
* [`metrics.global`](#metricsglobal)
* [`metrics.peers`](#metricspeers)
* [`metrics.protocols`](#metricsprotocols)
Expand Down Expand Up @@ -72,7 +83,8 @@ Creates an instance of Libp2p.
| [options.connectionManager] | `object` | libp2p Connection Manager configuration |
| [options.datastore] | `object` | must implement [ipfs/interface-datastore](https://github.com/ipfs/interface-datastore) (in memory datastore will be used if not provided) |
| [options.dialer] | `object` | libp2p Dialer configuration
| [options.metrics] | `object` | libp2p Metrics configuration
| [options.keychain] | [`object`](./CONFIGURATION.md#setup-with-keychain) | libp2p Keychain configuration |
| [options.metrics] | `object` | libp2p Metrics configuration |
| [options.peerId] | [`PeerId`][peer-id] | peerId instance (it will be created if not provided) |
| [options.peerStore] | `object` | libp2p PeerStore configuration |

Expand Down Expand Up @@ -1227,6 +1239,278 @@ libp2p.connectionManager.size
// 10
```
### keychain.createKey
Create a key in the keychain.
`libp2p.keychain.createKey(name, type, size)`
#### Parameters
| Name | Type | Description |
|------|------|-------------|
| name | `string` | The local key name. It cannot already exist. |
| type | `string` | One of the key types; 'rsa' |
| size | `number` | The key size in bits. |
#### Returns
| Type | Description |
|------|-------------|
| `Promise<{ id, name }>` | Key info object |
#### Example
```js
const keyInfo = await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
```
### keychain.renameKey
Rename a key in the keychain.
`libp2p.keychain.renameKey(oldName, newName)`
#### Parameters
| Name | Type | Description |
|------|------|-------------|
| name | `string` | The old local key name. It must already exist. |
| type | `string` | The new local key name. It must not already exist. |
#### Returns
| Type | Description |
|------|-------------|
| `Promise<{ id, name }>` | Key info object |
#### Example
```js
await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
const keyInfo = await libp2p.keychain.renameKey('keyTest', 'keyNewNtest')
```
### keychain.removeKey
Removes a key from the keychain.
`libp2p.keychain.removeKey(name)`
#### Parameters
| Name | Type | Description |
|------|------|-------------|
| name | `string` | The local key name. It must already exist. |
#### Returns
| Type | Description |
|------|-------------|
| `Promise<{ id, name }>` | Key info object |
#### Example
```js
await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
const keyInfo = await libp2p.keychain.removeKey('keyTest')
```
### keychain.exportKey
Export an existing key as a PEM encrypted PKCS #8 string.
`libp2p.keychain.exportKey(name, password)`
#### Parameters
| Name | Type | Description |
|------|------|-------------|
| name | `string` | The local key name. It must already exist. |
| password | `string` | The password to use. |
#### Returns
| Type | Description |
|------|-------------|
| `Promise<string>` | Key as a PEM encrypted PKCS #8 |
#### Example
```js
await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
const pemKey = await libp2p.keychain.exportKey('keyTest', 'password123')
```
### keychain.importKey
Import a new key from a PEM encoded PKCS #8 string.
`libp2p.keychain.importKey(name, pem, password)`
#### Parameters
| Name | Type | Description |
|------|------|-------------|
| name | `string` | The local key name. It must not exist. |
| pem | `string` | The PEM encoded PKCS #8 string. |
| password | `string` | The password to use. |
#### Returns
| Type | Description |
|------|-------------|
| `Promise<{ id, name }>` | Key info object |
#### Example
```js
await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
const pemKey = await libp2p.keychain.exportKey('keyTest', 'password123')
const keyInfo = await libp2p.keychain.importKey('keyTestImport', pemKey, 'password123')
```
### keychain.importPeer
Import a new key from a PeerId.
`libp2p.keychain.importPeer(name, peerId)`
#### Parameters
| Name | Type | Description |
|------|------|-------------|
| name | `string` | The local key name. It must not exist. |
| peerId | ['PeerId'][peer-id] | The PEM encoded PKCS #8 string. |
#### Returns
| Type | Description |
|------|-------------|
| `Promise<{ id, name }>` | Key info object |
#### Example
```js
const keyInfo = await libp2p.keychain.importPeer('keyTestImport', peerId)
```
### keychain.list
List all the keys.
`libp2p.keychain.list()`
#### Returns
| Type | Description |
|------|-------------|
| `Promise<Array<{ id, name }>>` | Array of Key info |
#### Example
```js
const keyInfos = await libp2p.keychain.list()
```
### keychain.findById
Find a key by it's id.

`libp2p.keychain.findById(id)`

#### Parameters

| Name | Type | Description |
|------|------|-------------|
| id | `string` | The universally unique key identifier. |

#### Returns

| Type | Description |
|------|-------------|
| `Promise<{ id, name }>` | Key info object |

#### Example

```js
const keyInfo = await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
const keyInfo2 = await libp2p.keychain.findById(keyInfo.id)
```

### keychain.findByName

Find a key by it's name.
`libp2p.keychain.findByName(id)`
#### Parameters
| Name | Type | Description |
|------|------|-------------|
| id | `string` | The local key name. |
#### Returns
| Type | Description |
|------|-------------|
| `Promise<{ id, name }>` | Key info object |
#### Example
```js
const keyInfo = await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
const keyInfo2 = await libp2p.keychain.findByName('keyTest')
```
### keychain.cms.encrypt
Encrypt protected data using the Cryptographic Message Syntax (CMS).
`libp2p.keychain.cms.encrypt(name, data)`
| Name | Type | Description |
|------|------|-------------|
| name | `string` | The local key name. |
| data | `Buffer` | The data to encrypt. |
#### Returns
| Type | Description |
|------|-------------|
| `Promise<Buffer>` | Encrypted data as a PKCS #7 message in DER. |
#### Example
```js
const keyInfo = await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
const enc = await libp2p.keychain.cms.encrypt('keyTest', Buffer.from('data'))
```
### keychain.cms.decrypt
Decrypt protected data using the Cryptographic Message Syntax (CMS).
The keychain must contain one of the keys used to encrypt the data. If none of the keys exists, an Error is returned with the property 'missingKeys'.
`libp2p.keychain.cms.decrypt(cmsData)`
| Name | Type | Description |
|------|------|-------------|
| cmsData | `string` | The CMS encrypted data to decrypt. |
#### Returns
| Type | Description |
|------|-------------|
| `Promise<Buffer>` | Decrypted data. |
#### Example
```js
const keyInfo = await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
const enc = await libp2p.keychain.cms.encrypt('keyTest', Buffer.from('data'))
```
### metrics.global
A [`Stats`](#stats) object of tracking the global bandwidth of the libp2p node.
Expand Down
30 changes: 30 additions & 0 deletions doc/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- [Customizing DHT](#customizing-dht)
- [Setup with Content and Peer Routing](#setup-with-content-and-peer-routing)
- [Setup with Relay](#setup-with-relay)
- [Setup with Keychain](#setup-with-keychain)
- [Configuring Dialing](#configuring-dialing)
- [Configuring Connection Manager](#configuring-connection-manager)
- [Configuring Metrics](#configuring-metrics)
Expand Down Expand Up @@ -422,6 +423,35 @@ const node = await Libp2p.create({
})
```

#### Setup with Keychain

Libp2p allows you to setup a secure key chain to manage your keys. The keychain configuration object should have the following properties:

| Name | Type | Description |
|------|------|-------------|
| pass | `string` | Passphrase to use in the keychain (minimum of 20 characters). |
| datastore | `object` | must implement [ipfs/interface-datastore](https://github.com/ipfs/interface-datastore) |

```js
const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const LevelStore = require('datastore-level')

const node = await Libp2p.create({
modules: {
transport: [TCP],
streamMuxer: [MPLEX],
connEncryption: [SECIO]
},
keychain: {
pass: 'notsafepassword123456789',
datastore: new LevelStore('path/to/store')
}
})
```

#### Configuring Dialing

Dialing in libp2p can be configured to limit the rate of dialing, and how long dials are allowed to take. The below configuration example shows the default values for the dialer.
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@
"multiaddr": "^7.4.3",
"multistream-select": "^0.15.0",
"mutable-proxy": "^1.0.0",
"node-forge": "^0.9.1",
"p-any": "^3.0.0",
"p-fifo": "^1.0.0",
"p-settle": "^4.0.1",
"peer-id": "^0.13.11",
"protons": "^1.0.1",
"retimer": "^2.0.0",
"sanitize-filename": "^1.6.3",
"streaming-iterables": "^4.1.0",
"timeout-abort-controller": "^1.0.0",
"xsalsa20": "^1.0.2"
Expand All @@ -95,19 +97,21 @@
"it-concat": "^1.0.0",
"it-pair": "^1.0.0",
"it-pushable": "^1.4.0",
"level": "^6.0.1",
"libp2p-bootstrap": "^0.11.0",
"libp2p-delegated-content-routing": "^0.5.0",
"libp2p-delegated-peer-routing": "^0.5.0",
"libp2p-floodsub": "^0.21.0",
"libp2p-gossipsub": "^0.4.0",
"libp2p-kad-dht": "^0.19.1",
"libp2p-mdns": "^0.14.1",
"libp2p-noise": "^1.1.0",
"libp2p-mplex": "^0.9.5",
"libp2p-noise": "^1.1.0",
"libp2p-secio": "^0.12.4",
"libp2p-tcp": "^0.14.1",
"libp2p-webrtc-star": "^0.18.0",
"libp2p-websockets": "^0.13.1",
"multihashes": "^0.4.19",
"nock": "^12.0.3",
"p-defer": "^3.0.0",
"p-times": "^3.0.0",
Expand Down
Loading

0 comments on commit 1df9134

Please sign in to comment.