mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-03-15 07:00:50 +00:00
fix!: load self key into keychain on startup if not present (#1357)
To prevent triggering keychain attack prevention on startup, refactor the `KeyChain` class to load the current PeerId as the `'self'` key on startup. Fixes #1315 BREAKING CHANGE: the `loadKeychain` method has been removed as it is no longer necessary
This commit is contained in:
parent
29c803a63e
commit
1f38ab7ac8
30
doc/API.md
30
doc/API.md
@ -185,36 +185,6 @@ Required keys in the `options` object:
|
|||||||
|
|
||||||
## Libp2p Instance Methods
|
## Libp2p Instance Methods
|
||||||
|
|
||||||
### loadKeychain
|
|
||||||
|
|
||||||
Load keychain keys from the datastore, importing the private key as 'self', if needed.
|
|
||||||
|
|
||||||
`libp2p.loadKeychain()`
|
|
||||||
|
|
||||||
#### Returns
|
|
||||||
|
|
||||||
| Type | Description |
|
|
||||||
|------|-------------|
|
|
||||||
| `Promise` | Promise resolves when the keychain is ready |
|
|
||||||
|
|
||||||
#### Example
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { createLibp2p } from 'libp2p'
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
const libp2p = await createLibp2p({
|
|
||||||
// ...
|
|
||||||
keychain: {
|
|
||||||
pass: '0123456789pass1234567890'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// load keychain
|
|
||||||
await libp2p.loadKeychain()
|
|
||||||
```
|
|
||||||
|
|
||||||
### start
|
### start
|
||||||
|
|
||||||
Starts the libp2p node.
|
Starts the libp2p node.
|
||||||
|
@ -494,8 +494,6 @@ const node = await createLibp2p({
|
|||||||
datastore: dsInstant,
|
datastore: dsInstant,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await node.loadKeychain()
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Configuring Dialing
|
#### Configuring Dialing
|
||||||
|
@ -140,12 +140,6 @@ export interface Libp2p extends Startable, EventEmitter<Libp2pEvents> {
|
|||||||
pubsub: PubSub
|
pubsub: PubSub
|
||||||
dht: DualDHT
|
dht: DualDHT
|
||||||
|
|
||||||
/**
|
|
||||||
* Load keychain keys from the datastore.
|
|
||||||
* Imports the private key as 'self', if needed.
|
|
||||||
*/
|
|
||||||
loadKeychain: () => Promise<void>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a deduplicated list of peer advertising multiaddrs by concatenating
|
* Get a deduplicated list of peer advertising multiaddrs by concatenating
|
||||||
* the listen addresses used by transports with any configured
|
* the listen addresses used by transports with any configured
|
||||||
|
@ -13,6 +13,7 @@ import { generateKeyPair, importKey, unmarshalPrivateKey } from '@libp2p/crypto/
|
|||||||
import type { PeerId } from '@libp2p/interface-peer-id'
|
import type { PeerId } from '@libp2p/interface-peer-id'
|
||||||
import type { Components } from '@libp2p/components'
|
import type { Components } from '@libp2p/components'
|
||||||
import { pbkdf2, randomBytes } from '@libp2p/crypto'
|
import { pbkdf2, randomBytes } from '@libp2p/crypto'
|
||||||
|
import type { Startable } from '@libp2p/interfaces/dist/src/startable'
|
||||||
|
|
||||||
const log = logger('libp2p:keychain')
|
const log = logger('libp2p:keychain')
|
||||||
|
|
||||||
@ -110,9 +111,10 @@ function DsInfoName (name: string) {
|
|||||||
* - '/pkcs8/*key-name*', contains the PKCS #8 for the key
|
* - '/pkcs8/*key-name*', contains the PKCS #8 for the key
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export class KeyChain {
|
export class KeyChain implements Startable {
|
||||||
private readonly components: Components
|
private readonly components: Components
|
||||||
private init: KeyChainInit
|
private init: KeyChainInit
|
||||||
|
private started: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of a key chain
|
* Creates a new instance of a key chain
|
||||||
@ -145,6 +147,25 @@ export class KeyChain {
|
|||||||
: ''
|
: ''
|
||||||
|
|
||||||
privates.set(this, { dek })
|
privates.set(this, { dek })
|
||||||
|
this.started = false
|
||||||
|
}
|
||||||
|
|
||||||
|
isStarted () {
|
||||||
|
return this.started
|
||||||
|
}
|
||||||
|
|
||||||
|
async start () {
|
||||||
|
const dsname = DsInfoName('self')
|
||||||
|
|
||||||
|
if (!(await this.components.getDatastore().has(dsname))) {
|
||||||
|
await this.importPeer('self', this.components.getPeerId())
|
||||||
|
}
|
||||||
|
|
||||||
|
this.started = true
|
||||||
|
}
|
||||||
|
|
||||||
|
stop () {
|
||||||
|
this.started = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -474,8 +495,11 @@ export class KeyChain {
|
|||||||
if (!validateKeyName(name)) {
|
if (!validateKeyName(name)) {
|
||||||
throw errCode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME)
|
throw errCode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME)
|
||||||
}
|
}
|
||||||
if (peer == null || peer.privateKey == null) {
|
if (peer == null) {
|
||||||
throw errCode(new Error('Peer.privKey is required'), codes.ERR_MISSING_PRIVATE_KEY)
|
throw errCode(new Error('PeerId is required'), codes.ERR_MISSING_PRIVATE_KEY)
|
||||||
|
}
|
||||||
|
if (peer.privateKey == null) {
|
||||||
|
throw errCode(new Error('PeerId.privKey is required'), codes.ERR_MISSING_PRIVATE_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
const privateKey = await unmarshalPrivateKey(peer.privateKey)
|
const privateKey = await unmarshalPrivateKey(peer.privateKey)
|
||||||
|
@ -352,22 +352,6 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
|
|||||||
log('libp2p has stopped')
|
log('libp2p has stopped')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Load keychain keys from the datastore.
|
|
||||||
* Imports the private key as 'self', if needed.
|
|
||||||
*/
|
|
||||||
async loadKeychain () {
|
|
||||||
if (this.keychain == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.keychain.findKeyByName('self')
|
|
||||||
} catch (err: any) {
|
|
||||||
await this.keychain.importPeer('self', this.peerId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isStarted () {
|
isStarted () {
|
||||||
return this.started
|
return this.started
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,10 @@ import type { Message, PublishResult, PubSubInit, PubSubRPC, PubSubRPCMessage }
|
|||||||
import type { Libp2pInit, Libp2pOptions } from '../../src/index.js'
|
import type { Libp2pInit, Libp2pOptions } from '../../src/index.js'
|
||||||
import type { PeerId } from '@libp2p/interface-peer-id'
|
import type { PeerId } from '@libp2p/interface-peer-id'
|
||||||
import * as cborg from 'cborg'
|
import * as cborg from 'cborg'
|
||||||
import { peerIdFromString } from '@libp2p/peer-id'
|
|
||||||
|
|
||||||
const relayAddr = MULTIADDRS_WEBSOCKETS[0]
|
const relayAddr = MULTIADDRS_WEBSOCKETS[0]
|
||||||
|
|
||||||
export const baseOptions: Partial<Libp2pInit> = {
|
export const baseOptions: Partial<Libp2pInit> = {
|
||||||
peerId: peerIdFromString('12D3KooWJKCJW8Y26pRFNv78TCMGLNTfyN8oKaFswMRYXTzSbSst'),
|
|
||||||
transports: [new WebSockets()],
|
transports: [new WebSockets()],
|
||||||
streamMuxers: [new Mplex()],
|
streamMuxers: [new Mplex()],
|
||||||
connectionEncryption: [new Plaintext()]
|
connectionEncryption: [new Plaintext()]
|
||||||
|
@ -512,8 +512,6 @@ describe('libp2p.keychain', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await libp2p.loadKeychain()
|
|
||||||
|
|
||||||
const kInfo = await libp2p.keychain.createKey('keyName', 'Ed25519')
|
const kInfo = await libp2p.keychain.createKey('keyName', 'Ed25519')
|
||||||
expect(kInfo).to.exist()
|
expect(kInfo).to.exist()
|
||||||
})
|
})
|
||||||
@ -526,8 +524,6 @@ describe('libp2p.keychain', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await libp2p.loadKeychain()
|
|
||||||
|
|
||||||
const kInfo = await libp2p.keychain.createKey('keyName', 'Ed25519')
|
const kInfo = await libp2p.keychain.createKey('keyName', 'Ed25519')
|
||||||
expect(kInfo).to.exist()
|
expect(kInfo).to.exist()
|
||||||
})
|
})
|
||||||
@ -543,7 +539,6 @@ describe('libp2p.keychain', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
await libp2p.loadKeychain()
|
|
||||||
|
|
||||||
const kInfo = await libp2p.keychain.createKey('keyName', 'Ed25519')
|
const kInfo = await libp2p.keychain.createKey('keyName', 'Ed25519')
|
||||||
expect(kInfo).to.exist()
|
expect(kInfo).to.exist()
|
||||||
@ -558,7 +553,6 @@ describe('libp2p.keychain', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await libp2p2.loadKeychain()
|
|
||||||
const key = await libp2p2.keychain.findKeyByName('keyName')
|
const key = await libp2p2.keychain.findKeyByName('keyName')
|
||||||
|
|
||||||
expect(key).to.exist()
|
expect(key).to.exist()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user