@libp2p/keychain 4.1.6 → 5.0.0-1210884ed

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,183 @@
1
+ import { randomBytes } from '@libp2p/crypto';
2
+ import { AES_GCM } from '@libp2p/crypto/ciphers';
3
+ import { privateKeyToProtobuf } from '@libp2p/crypto/keys';
4
+ import webcrypto from '@libp2p/crypto/webcrypto';
5
+ import { InvalidParametersError, UnsupportedKeyTypeError } from '@libp2p/interface';
6
+ import { pbkdf2Async } from '@noble/hashes/pbkdf2';
7
+ import { sha512 } from '@noble/hashes/sha512';
8
+ import * as asn1js from 'asn1js';
9
+ import { base64 } from 'multiformats/bases/base64';
10
+ import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
11
+ import { ITERATIONS, KEY_SIZE, SALT_LENGTH } from './constants.js';
12
+ /**
13
+ * Exports the given PrivateKey as a base64 encoded string.
14
+ * The PrivateKey is encrypted via a password derived PBKDF2 key
15
+ * leveraging the aes-gcm cipher algorithm.
16
+ */
17
+ export async function exporter(privateKey, password) {
18
+ const cipher = AES_GCM.create();
19
+ const encryptedKey = await cipher.encrypt(privateKey, password);
20
+ return base64.encode(encryptedKey);
21
+ }
22
+ /**
23
+ * Converts an exported private key into its representative object.
24
+ *
25
+ * Supported formats are 'pem' (RSA only) and 'libp2p-key'.
26
+ */
27
+ export async function exportPrivateKey(key, password, format) {
28
+ if (key.type === 'RSA') {
29
+ return exportRSAPrivateKey(key, password, format);
30
+ }
31
+ if (key.type === 'Ed25519') {
32
+ return exportEd25519PrivateKey(key, password, format);
33
+ }
34
+ if (key.type === 'secp256k1') {
35
+ return exportSecp256k1PrivateKey(key, password, format);
36
+ }
37
+ throw new UnsupportedKeyTypeError();
38
+ }
39
+ /**
40
+ * Exports the key into a password protected `format`
41
+ */
42
+ export async function exportEd25519PrivateKey(key, password, format = 'libp2p-key') {
43
+ if (format === 'libp2p-key') {
44
+ return exporter(privateKeyToProtobuf(key), password);
45
+ }
46
+ else {
47
+ throw new InvalidParametersError(`export format '${format}' is not supported`);
48
+ }
49
+ }
50
+ /**
51
+ * Exports the key into a password protected `format`
52
+ */
53
+ export async function exportSecp256k1PrivateKey(key, password, format = 'libp2p-key') {
54
+ if (format === 'libp2p-key') {
55
+ return exporter(privateKeyToProtobuf(key), password);
56
+ }
57
+ else {
58
+ throw new InvalidParametersError('Export format is not supported');
59
+ }
60
+ }
61
+ /**
62
+ * Exports the key as libp2p-key - a aes-gcm encrypted value with the key
63
+ * derived from the password.
64
+ *
65
+ * To export it as a password protected PEM file, please use the `exportPEM`
66
+ * function from `@libp2p/rsa`.
67
+ */
68
+ export async function exportRSAPrivateKey(key, password, format = 'pkcs-8') {
69
+ if (format === 'pkcs-8') {
70
+ return exportToPem(key, password);
71
+ }
72
+ else if (format === 'libp2p-key') {
73
+ return exporter(privateKeyToProtobuf(key), password);
74
+ }
75
+ else {
76
+ throw new InvalidParametersError('Export format is not supported');
77
+ }
78
+ }
79
+ export async function exportToPem(privateKey, password) {
80
+ const crypto = webcrypto.get();
81
+ // PrivateKeyInfo
82
+ const keyWrapper = new asn1js.Sequence({
83
+ value: [
84
+ // version (0)
85
+ new asn1js.Integer({ value: 0 }),
86
+ // privateKeyAlgorithm
87
+ new asn1js.Sequence({
88
+ value: [
89
+ // rsaEncryption OID
90
+ new asn1js.ObjectIdentifier({
91
+ value: '1.2.840.113549.1.1.1'
92
+ }),
93
+ new asn1js.Null()
94
+ ]
95
+ }),
96
+ // PrivateKey
97
+ new asn1js.OctetString({
98
+ valueHex: privateKey.raw
99
+ })
100
+ ]
101
+ });
102
+ const keyBuf = keyWrapper.toBER();
103
+ const keyArr = new Uint8Array(keyBuf, 0, keyBuf.byteLength);
104
+ const salt = randomBytes(SALT_LENGTH);
105
+ const encryptionKey = await pbkdf2Async(sha512, password, salt, {
106
+ c: ITERATIONS,
107
+ dkLen: KEY_SIZE
108
+ });
109
+ const iv = randomBytes(16);
110
+ const cryptoKey = await crypto.subtle.importKey('raw', encryptionKey, 'AES-CBC', false, ['encrypt']);
111
+ const encrypted = await crypto.subtle.encrypt({
112
+ name: 'AES-CBC',
113
+ iv
114
+ }, cryptoKey, keyArr);
115
+ const pbkdf2Params = new asn1js.Sequence({
116
+ value: [
117
+ // salt
118
+ new asn1js.OctetString({ valueHex: salt }),
119
+ // iteration count
120
+ new asn1js.Integer({ value: ITERATIONS }),
121
+ // key length
122
+ new asn1js.Integer({ value: KEY_SIZE }),
123
+ // AlgorithmIdentifier
124
+ new asn1js.Sequence({
125
+ value: [
126
+ // hmacWithSHA512
127
+ new asn1js.ObjectIdentifier({ value: '1.2.840.113549.2.11' }),
128
+ new asn1js.Null()
129
+ ]
130
+ })
131
+ ]
132
+ });
133
+ const encryptionAlgorithm = new asn1js.Sequence({
134
+ value: [
135
+ // pkcs5PBES2
136
+ new asn1js.ObjectIdentifier({
137
+ value: '1.2.840.113549.1.5.13'
138
+ }),
139
+ new asn1js.Sequence({
140
+ value: [
141
+ // keyDerivationFunc
142
+ new asn1js.Sequence({
143
+ value: [
144
+ // pkcs5PBKDF2
145
+ new asn1js.ObjectIdentifier({
146
+ value: '1.2.840.113549.1.5.12'
147
+ }),
148
+ // PBKDF2-params
149
+ pbkdf2Params
150
+ ]
151
+ }),
152
+ // encryptionScheme
153
+ new asn1js.Sequence({
154
+ value: [
155
+ // aes256-CBC
156
+ new asn1js.ObjectIdentifier({
157
+ value: '2.16.840.1.101.3.4.1.42'
158
+ }),
159
+ // iv
160
+ new asn1js.OctetString({
161
+ valueHex: iv
162
+ })
163
+ ]
164
+ })
165
+ ]
166
+ })
167
+ ]
168
+ });
169
+ const finalWrapper = new asn1js.Sequence({
170
+ value: [
171
+ encryptionAlgorithm,
172
+ new asn1js.OctetString({ valueHex: encrypted })
173
+ ]
174
+ });
175
+ const finalWrapperBuf = finalWrapper.toBER();
176
+ const finalWrapperArr = new Uint8Array(finalWrapperBuf, 0, finalWrapperBuf.byteLength);
177
+ return [
178
+ '-----BEGIN ENCRYPTED PRIVATE KEY-----',
179
+ ...uint8ArrayToString(finalWrapperArr, 'base64pad').split(/(.{64})/).filter(Boolean),
180
+ '-----END ENCRYPTED PRIVATE KEY-----'
181
+ ].join('\n');
182
+ }
183
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../../src/utils/export.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { PrivateKey, RSAPrivateKey } from '@libp2p/interface';
2
+ /**
3
+ * Converts an exported private key into its representative object.
4
+ *
5
+ * Supported formats are 'pem' (RSA only) and 'libp2p-key'.
6
+ */
7
+ export declare function importPrivateKey(encryptedKey: string, password: string): Promise<PrivateKey>;
8
+ /**
9
+ * Attempts to decrypt a base64 encoded PrivateKey string
10
+ * with the given password. The privateKey must have been exported
11
+ * using the same password and underlying cipher (aes-gcm)
12
+ */
13
+ export declare function importer(privateKey: string, password: string): Promise<Uint8Array>;
14
+ export declare function importFromPem(pem: string, password: string): Promise<RSAPrivateKey>;
15
+ //# sourceMappingURL=import.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../../src/utils/import.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAElE;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAanG;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAIzF;AAED,wBAAsB,aAAa,CAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAiE1F"}
@@ -0,0 +1,137 @@
1
+ import { AES_GCM } from '@libp2p/crypto/ciphers';
2
+ import { privateKeyFromProtobuf, privateKeyFromRaw } from '@libp2p/crypto/keys';
3
+ import webcrypto from '@libp2p/crypto/webcrypto';
4
+ import { InvalidParametersError } from '@libp2p/interface';
5
+ import { pbkdf2Async } from '@noble/hashes/pbkdf2';
6
+ import { sha512 } from '@noble/hashes/sha512';
7
+ import * as asn1js from 'asn1js';
8
+ import { base64 } from 'multiformats/bases/base64';
9
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
10
+ import { ITERATIONS, KEY_SIZE } from './constants.js';
11
+ /**
12
+ * Converts an exported private key into its representative object.
13
+ *
14
+ * Supported formats are 'pem' (RSA only) and 'libp2p-key'.
15
+ */
16
+ export async function importPrivateKey(encryptedKey, password) {
17
+ try {
18
+ const key = await importer(encryptedKey, password);
19
+ return privateKeyFromProtobuf(key);
20
+ }
21
+ catch {
22
+ // Ignore and try the old pem decrypt
23
+ }
24
+ if (!encryptedKey.includes('BEGIN')) {
25
+ throw new InvalidParametersError('Encrypted key was not a libp2p-key or a PEM file');
26
+ }
27
+ return importFromPem(encryptedKey, password);
28
+ }
29
+ /**
30
+ * Attempts to decrypt a base64 encoded PrivateKey string
31
+ * with the given password. The privateKey must have been exported
32
+ * using the same password and underlying cipher (aes-gcm)
33
+ */
34
+ export async function importer(privateKey, password) {
35
+ const encryptedKey = base64.decode(privateKey);
36
+ const cipher = AES_GCM.create();
37
+ return cipher.decrypt(encryptedKey, password);
38
+ }
39
+ export async function importFromPem(pem, password) {
40
+ const crypto = webcrypto.get();
41
+ let plaintext;
42
+ if (pem.includes('-----BEGIN ENCRYPTED PRIVATE KEY-----')) {
43
+ const key = uint8ArrayFromString(pem
44
+ .replace('-----BEGIN ENCRYPTED PRIVATE KEY-----', '')
45
+ .replace('-----END ENCRYPTED PRIVATE KEY-----', '')
46
+ .replace(/\n/g, '')
47
+ .trim(), 'base64pad');
48
+ const { result } = asn1js.fromBER(key);
49
+ const { iv, salt, iterations, keySize, cipherText } = findEncryptedPEMData(result);
50
+ const encryptionKey = await pbkdf2Async(sha512, password, salt, {
51
+ c: iterations,
52
+ dkLen: keySize
53
+ });
54
+ const cryptoKey = await crypto.subtle.importKey('raw', encryptionKey, 'AES-CBC', false, ['decrypt']);
55
+ const decrypted = toUint8Array(await crypto.subtle.decrypt({
56
+ name: 'AES-CBC',
57
+ iv
58
+ }, cryptoKey, cipherText));
59
+ const { result: decryptedResult } = asn1js.fromBER(decrypted);
60
+ plaintext = findPEMData(decryptedResult);
61
+ }
62
+ else if (pem.includes('-----BEGIN PRIVATE KEY-----')) {
63
+ const key = uint8ArrayFromString(pem
64
+ .replace('-----BEGIN PRIVATE KEY-----', '')
65
+ .replace('-----END PRIVATE KEY-----', '')
66
+ .replace(/\n/g, '')
67
+ .trim(), 'base64pad');
68
+ const { result } = asn1js.fromBER(key);
69
+ plaintext = findPEMData(result);
70
+ }
71
+ else {
72
+ throw new InvalidParametersError('Could not parse private key from PEM data');
73
+ }
74
+ const key = privateKeyFromRaw(plaintext);
75
+ if (key.type !== 'RSA') {
76
+ throw new InvalidParametersError('Could not parse RSA private key from PEM data');
77
+ }
78
+ return key;
79
+ }
80
+ function findEncryptedPEMData(root) {
81
+ const encryptionAlgorithm = root.valueBlock.value[0];
82
+ const scheme = encryptionAlgorithm.valueBlock.value[0].toString();
83
+ if (scheme !== 'OBJECT IDENTIFIER : 1.2.840.113549.1.5.13') {
84
+ throw new InvalidParametersError('Only pkcs5PBES2 encrypted private keys are supported');
85
+ }
86
+ const keyDerivationFunc = encryptionAlgorithm.valueBlock.value[1].valueBlock.value[0];
87
+ const keyDerivationFuncName = keyDerivationFunc.valueBlock.value[0].toString();
88
+ if (keyDerivationFuncName !== 'OBJECT IDENTIFIER : 1.2.840.113549.1.5.12') {
89
+ throw new InvalidParametersError('Only pkcs5PBKDF2 key derivation functions are supported');
90
+ }
91
+ const pbkdf2Params = keyDerivationFunc.valueBlock.value[1];
92
+ const salt = toUint8Array(pbkdf2Params.valueBlock.value[0].getValue());
93
+ let iterations = ITERATIONS;
94
+ let keySize = KEY_SIZE;
95
+ if (pbkdf2Params.valueBlock.value.length === 3) {
96
+ iterations = Number(pbkdf2Params.valueBlock.value[1].toBigInt());
97
+ keySize = Number((pbkdf2Params.valueBlock.value[2]).toBigInt());
98
+ }
99
+ else if (pbkdf2Params.valueBlock.value.length === 2) {
100
+ throw new InvalidParametersError('Could not derive key size and iterations from PEM file - please use @libp2p/rsa to re-import your key');
101
+ }
102
+ const encryptionScheme = encryptionAlgorithm.valueBlock.value[1].valueBlock.value[1];
103
+ const encryptionSchemeName = encryptionScheme.valueBlock.value[0].toString();
104
+ if (encryptionSchemeName === 'OBJECT IDENTIFIER : 1.2.840.113549.3.7') {
105
+ // des-EDE3-CBC
106
+ }
107
+ else if (encryptionSchemeName === 'OBJECT IDENTIFIER : 1.3.14.3.2.7') {
108
+ // des-CBC
109
+ }
110
+ else if (encryptionSchemeName === 'OBJECT IDENTIFIER : 2.16.840.1.101.3.4.1.2') {
111
+ // aes128-CBC
112
+ }
113
+ else if (encryptionSchemeName === 'OBJECT IDENTIFIER : 2.16.840.1.101.3.4.1.22') {
114
+ // aes192-CBC
115
+ }
116
+ else if (encryptionSchemeName === 'OBJECT IDENTIFIER : 2.16.840.1.101.3.4.1.42') {
117
+ // aes256-CBC
118
+ }
119
+ else {
120
+ throw new InvalidParametersError('Only AES-CBC encryption schemes are supported');
121
+ }
122
+ const iv = toUint8Array(encryptionScheme.valueBlock.value[1].getValue());
123
+ return {
124
+ cipherText: toUint8Array(root.valueBlock.value[1].getValue()),
125
+ salt,
126
+ iterations,
127
+ keySize,
128
+ iv
129
+ };
130
+ }
131
+ function findPEMData(seq) {
132
+ return toUint8Array(seq.valueBlock.value[2].getValue());
133
+ }
134
+ function toUint8Array(buf) {
135
+ return new Uint8Array(buf, 0, buf.byteLength);
136
+ }
137
+ //# sourceMappingURL=import.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.js","sourceRoot":"","sources":["../../../src/utils/import.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@libp2p/keychain",
3
- "version": "4.1.6",
3
+ "version": "5.0.0-1210884ed",
4
4
  "description": "Key management and cryptographically protected messages",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/keychain#readme",
@@ -59,20 +59,20 @@
59
59
  "test:electron-main": "aegir test -t electron-main"
60
60
  },
61
61
  "dependencies": {
62
- "@libp2p/crypto": "^4.1.9",
63
- "@libp2p/interface": "^1.7.0",
64
- "@libp2p/peer-id": "^4.2.4",
65
- "interface-datastore": "^8.2.11",
62
+ "@libp2p/crypto": "5.0.0-1210884ed",
63
+ "@libp2p/interface": "2.0.0-1210884ed",
64
+ "@noble/hashes": "^1.5.0",
65
+ "asn1js": "^3.0.5",
66
+ "interface-datastore": "^8.3.0",
66
67
  "merge-options": "^3.0.4",
67
- "multiformats": "^13.1.0",
68
+ "multiformats": "^13.2.2",
68
69
  "sanitize-filename": "^1.6.3",
69
70
  "uint8arrays": "^5.1.0"
70
71
  },
71
72
  "devDependencies": {
72
- "@libp2p/logger": "^4.0.20",
73
- "@libp2p/peer-id-factory": "^4.2.4",
73
+ "@libp2p/logger": "5.0.0-1210884ed",
74
74
  "aegir": "^44.0.1",
75
- "datastore-core": "^9.2.9"
75
+ "datastore-core": "^10.0.0"
76
76
  },
77
77
  "sideEffects": false
78
78
  }
package/src/index.ts CHANGED
@@ -51,10 +51,9 @@
51
51
  * A key benefit is that now the key chain can be used in browser with the [js-datastore-level](https://github.com/ipfs/js-datastore-level) implementation.
52
52
  */
53
53
 
54
- import { DefaultKeychain } from './keychain.js'
55
- import type { ComponentLogger, KeyType, PeerId } from '@libp2p/interface'
54
+ import { Keychain as KeychainClass } from './keychain.js'
55
+ import type { ComponentLogger, PrivateKey } from '@libp2p/interface'
56
56
  import type { Datastore } from 'interface-datastore'
57
- import type { Multibase } from 'multiformats/bases/interface.js'
58
57
 
59
58
  export interface DEKConfig {
60
59
  hash: string
@@ -87,73 +86,63 @@ export interface KeyInfo {
87
86
 
88
87
  export interface Keychain {
89
88
  /**
90
- * Export an existing key as a PEM encrypted PKCS #8 string.
89
+ * Find a key by name
91
90
  *
92
91
  * @example
93
92
  *
94
93
  * ```TypeScript
95
- * await libp2p.services.keychain.createKey('keyTest', 'RSA', 4096)
96
- * const pemKey = await libp2p.services.keychain.exportKey('keyTest', 'password123')
97
- * ```
98
- */
99
- exportKey(name: string, password: string): Promise<Multibase<'m'>>
100
-
101
- /**
102
- * Import a new key from a PEM encoded PKCS #8 string.
103
- *
104
- * @example
94
+ * import { generateKeyPair } from '@libp2p/crypto/keys'
105
95
  *
106
- * ```TypeScript
107
- * await libp2p.services.keychain.createKey('keyTest', 'RSA', 4096)
108
- * const pemKey = await libp2p.services.keychain.exportKey('keyTest', 'password123')
109
- * const keyInfo = await libp2p.services.keychain.importKey('keyTestImport', pemKey, 'password123')
96
+ * const key = await generateKeyPair('Ed25519')
97
+ * const keyInfo = await libp2p.keychain.importKey('my-key', key)
98
+ * const keyInfo2 = await libp2p.keychain.findKeyByName(keyInfo.name)
110
99
  * ```
111
100
  */
112
- importKey(name: string, pem: string, password: string): Promise<KeyInfo>
101
+ findKeyByName(name: string): Promise<KeyInfo>
113
102
 
114
103
  /**
115
- * Import a new key from a PeerId with a private key component
104
+ * Find a key by id
116
105
  *
117
106
  * @example
118
107
  *
119
108
  * ```TypeScript
120
- * const keyInfo = await libp2p.services.keychain.importPeer('keyTestImport', peerIdFromString('12D3Foo...'))
121
- * ```
122
- */
123
- importPeer(name: string, peerId: PeerId): Promise<KeyInfo>
124
-
125
- /**
126
- * Export an existing key as a PeerId
127
- *
128
- * @example
109
+ * import { generateKeyPair } from '@libp2p/crypto/keys'
129
110
  *
130
- * ```TypeScript
131
- * const peerId = await libp2p.services.keychain.exportPeerId('key-name')
111
+ * const key = await generateKeyPair('Ed25519')
112
+ * const keyInfo = await libp2p.keychain.importKey('my-key', key)
113
+ * const keyInfo2 = await libp2p.keychain.findKeyById(keyInfo.id)
132
114
  * ```
133
115
  */
134
- exportPeerId(name: string): Promise<PeerId>
116
+ findKeyById (id: string): Promise<KeyInfo>
135
117
 
136
118
  /**
137
- * Create a key in the keychain.
119
+ * Import a new private key.
138
120
  *
139
121
  * @example
140
122
  *
141
123
  * ```TypeScript
142
- * const keyInfo = await libp2p.services.keychain.createKey('keyTest', 'RSA', 4096)
124
+ * import { generateKeyPair } from '@libp2p/crypto/keys'
125
+ *
126
+ * const key = await generateKeyPair('Ed25519')
127
+ * const keyInfo = await libp2p.keychain.importKey('my-key', key)
143
128
  * ```
144
129
  */
145
- createKey(name: string, type: KeyType, size?: number): Promise<KeyInfo>
130
+ importKey(name: string, key: PrivateKey): Promise<KeyInfo>
146
131
 
147
132
  /**
148
- * List all the keys.
133
+ * Export an existing private key.
149
134
  *
150
135
  * @example
151
136
  *
152
137
  * ```TypeScript
153
- * const keyInfos = await libp2p.services.keychain.listKeys()
138
+ * import { generateKeyPair } from '@libp2p/crypto/keys'
139
+ *
140
+ * const key = await generateKeyPair('Ed25519')
141
+ * const keyInfo = await libp2p.keychain.importKey('my-key', key)
142
+ * const key = await libp2p.keychain.exportKey(keyInfo.id)
154
143
  * ```
155
144
  */
156
- listKeys(): Promise<KeyInfo[]>
145
+ exportKey(name: string): Promise<PrivateKey>
157
146
 
158
147
  /**
159
148
  * Removes a key from the keychain.
@@ -168,7 +157,8 @@ export interface Keychain {
168
157
  removeKey(name: string): Promise<KeyInfo>
169
158
 
170
159
  /**
171
- * Rename a key in the keychain.
160
+ * Rename a key in the keychain. This is done in a batch commit with rollback
161
+ * so errors thrown during the operation will not cause key loss.
172
162
  *
173
163
  * @example
174
164
  *
@@ -180,28 +170,15 @@ export interface Keychain {
180
170
  renameKey(oldName: string, newName: string): Promise<KeyInfo>
181
171
 
182
172
  /**
183
- * Find a key by it's id.
184
- *
185
- * @example
186
- *
187
- * ```TypeScript
188
- * const keyInfo = await libp2p.services.keychain.createKey('keyTest', 'RSA', 4096)
189
- * const keyInfo2 = await libp2p.services.keychain.findKeyById(keyInfo.id)
190
- * ```
191
- */
192
- findKeyById(id: string): Promise<KeyInfo>
193
-
194
- /**
195
- * Find a key by it's name.
173
+ * List all the keys.
196
174
  *
197
175
  * @example
198
176
  *
199
177
  * ```TypeScript
200
- * const keyInfo = await libp2p.services.keychain.createKey('keyTest', 'RSA', 4096)
201
- * const keyInfo2 = await libp2p.services.keychain.findKeyByName('keyTest')
178
+ * const keyInfos = await libp2p.keychain.listKeys()
202
179
  * ```
203
180
  */
204
- findKeyByName(name: string): Promise<KeyInfo>
181
+ listKeys(): Promise<KeyInfo[]>
205
182
 
206
183
  /**
207
184
  * Rotate keychain password and re-encrypt all associated keys
@@ -217,6 +194,6 @@ export interface Keychain {
217
194
 
218
195
  export function keychain (init: KeychainInit = {}): (components: KeychainComponents) => Keychain {
219
196
  return (components: KeychainComponents) => {
220
- return new DefaultKeychain(components, init)
197
+ return new KeychainClass(components, init)
221
198
  }
222
199
  }