@@ -10,13 +10,12 @@ import { sha256 } from 'multiformats/hashes/sha2'
10
10
import sanitize from 'sanitize-filename'
11
11
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
12
12
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
13
- import { exportPrivateKey , exporter } from './utils/export.js'
14
- import { importPrivateKey , importer } from './utils/import.js'
15
- import type { KeychainComponents , KeychainInit , Keychain as KeychainInterface , KeyInfo , X509Info } from './index.js'
13
+ import { exportPrivateKey } from './utils/export.js'
14
+ import { importPrivateKey } from './utils/import.js'
15
+ import type { KeychainComponents , KeychainInit , Keychain as KeychainInterface , KeyInfo } from './index.js'
16
16
import type { Logger , PrivateKey } from '@libp2p/interface'
17
17
18
18
const keyPrefix = '/pkcs8/'
19
- const certPrefix = '/x509/'
20
19
const infoPrefix = '/info/'
21
20
const privates = new WeakMap < object , { dek : string } > ( )
22
21
@@ -64,8 +63,8 @@ async function randomDelay (): Promise<void> {
64
63
/**
65
64
* Converts a key name into a datastore name
66
65
*/
67
- function DsName ( prefix : string , name : string ) : Key {
68
- return new Key ( prefix + name )
66
+ function DsName ( name : string ) : Key {
67
+ return new Key ( keyPrefix + name )
69
68
}
70
69
71
70
/**
@@ -207,7 +206,7 @@ export class Keychain implements KeychainInterface {
207
206
await randomDelay ( )
208
207
throw new InvalidParametersError ( 'Key is required' )
209
208
}
210
- const datastoreName = DsName ( keyPrefix , name )
209
+ const datastoreName = DsName ( name )
211
210
const exists = await this . components . datastore . has ( datastoreName )
212
211
if ( exists ) {
213
212
await randomDelay ( )
@@ -249,7 +248,7 @@ export class Keychain implements KeychainInterface {
249
248
throw new InvalidParametersError ( `Invalid key name '${ name } '` )
250
249
}
251
250
252
- const datastoreName = DsName ( keyPrefix , name )
251
+ const datastoreName = DsName ( name )
253
252
try {
254
253
const res = await this . components . datastore . get ( datastoreName )
255
254
const pem = uint8ArrayToString ( res )
@@ -274,7 +273,7 @@ export class Keychain implements KeychainInterface {
274
273
throw new InvalidParametersError ( `Invalid key name '${ name } '` )
275
274
}
276
275
277
- const datastoreName = DsName ( keyPrefix , name )
276
+ const datastoreName = DsName ( name )
278
277
const keyInfo = await this . findKeyByName ( name )
279
278
const batch = this . components . datastore . batch ( )
280
279
batch . delete ( datastoreName )
@@ -318,8 +317,8 @@ export class Keychain implements KeychainInterface {
318
317
await randomDelay ( )
319
318
throw new InvalidParametersError ( `Invalid new key name '${ newName } '` )
320
319
}
321
- const oldDatastoreName = DsName ( keyPrefix , oldName )
322
- const newDatastoreName = DsName ( keyPrefix , newName )
320
+ const oldDatastoreName = DsName ( oldName )
321
+ const newDatastoreName = DsName ( newName )
323
322
const oldInfoName = DsInfoName ( oldName )
324
323
const newInfoName = DsInfoName ( newName )
325
324
@@ -348,99 +347,6 @@ export class Keychain implements KeychainInterface {
348
347
}
349
348
}
350
349
351
- /**
352
- * List all the certificates
353
- */
354
- async listX509 ( ) : Promise < X509Info [ ] > {
355
- const query = {
356
- prefix : certPrefix
357
- }
358
-
359
- const info = [ ]
360
- for await ( const value of this . components . datastore . query ( query ) ) {
361
- info . push ( {
362
- name : value . key . toString ( ) . replace ( certPrefix , '' )
363
- } )
364
- }
365
-
366
- return info
367
- }
368
-
369
- async importX509 ( name : string , pem : string ) : Promise < void > {
370
- try {
371
- if ( ! validateKeyName ( name ) ) {
372
- throw new InvalidParametersError ( `Invalid certificate name '${ name } '` )
373
- }
374
-
375
- if ( pem == null ) {
376
- throw new InvalidParametersError ( 'PEM is required' )
377
- }
378
-
379
- if ( ! pem . includes ( '-----BEGIN CERTIFICATE-----' ) && ! pem . includes ( '-----END CERTIFICATE-----' ) ) {
380
- throw new InvalidParametersError ( 'PEM was invalid' )
381
- }
382
-
383
- const datastoreName = DsName ( certPrefix , name )
384
-
385
- const exists = await this . components . datastore . has ( datastoreName )
386
- if ( exists ) {
387
- throw new InvalidParametersError ( `Certificate '${ name } ' already exists` )
388
- }
389
-
390
- const cached = privates . get ( this )
391
-
392
- if ( cached == null ) {
393
- throw new InvalidParametersError ( 'dek missing' )
394
- }
395
-
396
- const dek = cached . dek
397
- const dsPem = await exporter ( uint8ArrayFromString ( pem ) , dek )
398
- await this . components . datastore . put ( datastoreName , uint8ArrayFromString ( dsPem ) )
399
- } catch ( err ) {
400
- await randomDelay ( )
401
- throw err
402
- }
403
- }
404
-
405
- async exportX509 ( name : string ) : Promise < string > {
406
- try {
407
- if ( ! validateKeyName ( name ) ) {
408
- throw new InvalidParametersError ( `Invalid key name '${ name } '` )
409
- }
410
-
411
- const datastoreName = DsName ( certPrefix , name )
412
- const res = await this . components . datastore . get ( datastoreName )
413
- const encryptedPem = uint8ArrayToString ( res )
414
- const cached = privates . get ( this )
415
-
416
- if ( cached == null ) {
417
- throw new InvalidParametersError ( 'dek missing' )
418
- }
419
-
420
- const dek = cached . dek
421
- const buf = await importer ( encryptedPem , dek )
422
-
423
- return uint8ArrayToString ( buf )
424
- } catch ( err : any ) {
425
- await randomDelay ( )
426
- throw err
427
- }
428
- }
429
-
430
- async removeX509 ( name : string ) : Promise < void > {
431
- try {
432
- if ( ! validateKeyName ( name ) || name === this . self ) {
433
- throw new InvalidParametersError ( `Invalid key name '${ name } '` )
434
- }
435
-
436
- const datastoreName = DsName ( certPrefix , name )
437
- await this . components . datastore . delete ( datastoreName )
438
- } catch ( err ) {
439
- await randomDelay ( )
440
- throw err
441
- }
442
- }
443
-
444
350
/**
445
351
* Rotate keychain password and re-encrypt all associated keys
446
352
*/
@@ -475,33 +381,24 @@ export class Keychain implements KeychainInterface {
475
381
this . init . dek ?. hash )
476
382
: ''
477
383
privates . set ( this , { dek : newDek } )
478
-
479
- const batch = this . components . datastore . batch ( )
480
-
481
- for ( const key of await this . listKeys ( ) ) {
482
- const res = await this . components . datastore . get ( DsName ( keyPrefix , key . name ) )
384
+ const keys = await this . listKeys ( )
385
+ for ( const key of keys ) {
386
+ const res = await this . components . datastore . get ( DsName ( key . name ) )
483
387
const pem = uint8ArrayToString ( res )
484
388
const privateKey = await importPrivateKey ( pem , oldDek )
485
389
const password = newDek . toString ( )
486
390
const keyAsPEM = await exportPrivateKey ( privateKey , password , privateKey . type === 'RSA' ? 'pkcs-8' : 'libp2p-key' )
487
391
488
- // add to batch
489
- batch . put ( DsName ( keyPrefix , key . name ) , uint8ArrayFromString ( keyAsPEM ) )
490
- }
491
-
492
- for ( const key of await this . listX509 ( ) ) {
493
- // decrypt using old password and encrypt using new
494
- const res = await this . components . datastore . get ( DsName ( certPrefix , key . name ) )
495
- const pem = uint8ArrayToString ( res )
496
- const decrypted = await importer ( pem , oldDek )
497
- const encrypted = await exporter ( decrypted , newDek )
498
-
499
- // add to batch
500
- batch . put ( DsName ( certPrefix , key . name ) , uint8ArrayFromString ( encrypted ) )
392
+ // Update stored key
393
+ const batch = this . components . datastore . batch ( )
394
+ const keyInfo = {
395
+ name : key . name ,
396
+ id : key . id
397
+ }
398
+ batch . put ( DsName ( key . name ) , uint8ArrayFromString ( keyAsPEM ) )
399
+ batch . put ( DsInfoName ( key . name ) , uint8ArrayFromString ( JSON . stringify ( keyInfo ) ) )
400
+ await batch . commit ( )
501
401
}
502
-
503
- await batch . commit ( )
504
-
505
402
this . log ( 'keychain reconstructed' )
506
403
}
507
404
}
0 commit comments