Skip to content

Commit 141e072

Browse files
authored
fix: allow exporting PeerIds from the keychain (#1546)
We can import a PeerId but not export it, so this PR adds the ability to export a PeerId. This is useful for IPNS and other things that need the ability to act on PeerIds stored in the keychain.
1 parent 5cf7f48 commit 141e072

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

src/keychain/index.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import type { PeerId } from '@libp2p/interface-peer-id'
1414
import { pbkdf2, randomBytes } from '@libp2p/crypto'
1515
import type { Startable } from '@libp2p/interfaces/dist/src/startable'
1616
import type { Datastore } from 'interface-datastore'
17+
import { peerIdFromKeys } from '@libp2p/peer-id'
18+
import type { KeyTypes } from '@libp2p/crypto/keys'
1719

1820
const log = logger('libp2p:keychain')
1921

@@ -222,7 +224,7 @@ export class KeyChain implements Startable {
222224
* @param {string} type - One of the key types; 'rsa'.
223225
* @param {number} [size = 2048] - The key size in bits. Used for rsa keys only
224226
*/
225-
async createKey (name: string, type: 'RSA' | 'Ed25519', size = 2048): Promise<KeyInfo> {
227+
async createKey (name: string, type: KeyTypes, size = 2048): Promise<KeyInfo> {
226228
if (!validateKeyName(name) || name === 'self') {
227229
await randomDelay()
228230
throw errCode(new Error('Invalid key name'), codes.ERR_INVALID_KEY_NAME)
@@ -432,6 +434,17 @@ export class KeyChain implements Startable {
432434
}
433435
}
434436

437+
/**
438+
* Export an existing key as a PeerId
439+
*/
440+
async exportPeerId (name: string) {
441+
const password = 'temporary-password'
442+
const pem = await this.exportKey(name, password)
443+
const privateKey = await importKey(pem, password)
444+
445+
return await peerIdFromKeys(privateKey.public.bytes, privateKey.bytes)
446+
}
447+
435448
/**
436449
* Import a new key from a PEM encoded PKCS #8 string
437450
*

test/keychain/keychain.spec.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,14 @@ describe('keychain', () => {
373373
expect(key.id).to.equal(alice.toString())
374374
})
375375

376+
it('private key can be exported', async () => {
377+
const alice2 = await ks.exportPeerId('alice')
378+
379+
expect(alice.equals(alice2)).to.be.true()
380+
expect(alice2).to.have.property('privateKey').that.is.ok()
381+
expect(alice2).to.have.property('publicKey').that.is.ok()
382+
})
383+
376384
it('private key import requires a valid name', async () => {
377385
// @ts-expect-error invalid parameters
378386
await expect(ks.importPeer(undefined, alice)).to.eventually.be.rejected.with.property('code', 'ERR_INVALID_KEY_NAME')
@@ -396,6 +404,36 @@ describe('keychain', () => {
396404
expect(key).to.have.property('name', 'alice')
397405
expect(key).to.have.property('id', alice.toString())
398406
})
407+
408+
it('can create Ed25519 peer id', async () => {
409+
const name = 'ed-key'
410+
await ks.createKey(name, 'Ed25519')
411+
const peer = await ks.exportPeerId(name)
412+
413+
expect(peer).to.have.property('type', 'Ed25519')
414+
expect(peer).to.have.property('privateKey').that.is.ok()
415+
expect(peer).to.have.property('publicKey').that.is.ok()
416+
})
417+
418+
it('can create RSA peer id', async () => {
419+
const name = 'rsa-key'
420+
await ks.createKey(name, 'RSA', 2048)
421+
const peer = await ks.exportPeerId(name)
422+
423+
expect(peer).to.have.property('type', 'RSA')
424+
expect(peer).to.have.property('privateKey').that.is.ok()
425+
expect(peer).to.have.property('publicKey').that.is.ok()
426+
})
427+
428+
it('can create secp256k1 peer id', async () => {
429+
const name = 'secp256k1-key'
430+
await ks.createKey(name, 'secp256k1')
431+
const peer = await ks.exportPeerId(name)
432+
433+
expect(peer).to.have.property('type', 'secp256k1')
434+
expect(peer).to.have.property('privateKey').that.is.ok()
435+
expect(peer).to.have.property('publicKey').that.is.ok()
436+
})
399437
})
400438

401439
describe('rename', () => {

0 commit comments

Comments
 (0)