@@ -2,6 +2,7 @@ import { AgentContext, Kms } from "@credo-ts/core";
22import { ec as EC } from "elliptic" ;
33import _sodium from "libsodium-wrappers" ;
44import sjcl from "sjcl" ;
5+ import { KeyStorage } from "./KeyStorage" ;
56
67export interface JwkKeyPair {
78 publicKey : JsonWebKey ;
@@ -10,10 +11,9 @@ export interface JwkKeyPair {
1011}
1112
1213export class EnmshedHolderKeyManagmentService implements Kms . KeyManagementService {
13- public static readonly backend = "fakeKeyManagementService " ;
14+ public static readonly backend = "enmeshed " ;
1415
1516 public readonly backend = EnmshedHolderKeyManagmentService . backend ;
16- public keystore : Map < string , string > ;
1717
1818 private readonly b64url = ( bytes : Uint8Array ) => _sodium . to_base64 ( bytes , _sodium . base64_variants . URLSAFE_NO_PADDING ) ;
1919 private readonly b64urlDecode = ( b64url : string ) => _sodium . from_base64 ( b64url , _sodium . base64_variants . URLSAFE_NO_PADDING ) ;
@@ -33,20 +33,7 @@ export class EnmshedHolderKeyManagmentService implements Kms.KeyManagementServic
3333 return bytes ;
3434 } ;
3535
36- public constructor ( ) {
37- if ( ( globalThis as any ) . fakeKeyStorage ) {
38- this . keystore = ( globalThis as any ) . fakeKeyStorage ;
39- } else {
40- this . keystore = new Map < string , string > ( ) ;
41- }
42- this . updateGlobalInstance ( this . keystore ) ;
43- }
44-
45- public updateGlobalInstance ( storage : Map < string , string > ) : void {
46- // console.log(`FKM: updating global instance ${JSON.stringify(Array.from(storage.entries()))}`);
47- ( globalThis as any ) . fakeKeyStorage = storage ;
48- // console.log(`FKM: global instance state ${JSON.stringify(Array.from((globalThis as any).fakeKeyStorage.entries()))}`);
49- }
36+ public constructor ( private readonly keyStorage : KeyStorage ) { }
5037
5138 public isOperationSupported ( agentContext : AgentContext , operation : Kms . KmsOperation ) : boolean {
5239 agentContext . config . logger . debug ( `EKM: Checking if operation is supported: ${ JSON . stringify ( operation ) } ` ) ;
@@ -76,14 +63,14 @@ export class EnmshedHolderKeyManagmentService implements Kms.KeyManagementServic
7663 }
7764 return false ;
7865 }
79- public getPublicKey ( agentContext : AgentContext , keyId : string ) : Promise < Kms . KmsJwkPublic > {
80- const keyPair = this . keystore . get ( keyId ) ;
66+ public async getPublicKey ( agentContext : AgentContext , keyId : string ) : Promise < Kms . KmsJwkPublic > {
67+ const keyPair = await this . keyStorage . getKey ( keyId ) ;
8168 if ( ! keyPair ) {
8269 agentContext . config . logger . error ( `EKM: Key with id ${ keyId } not found` ) ;
8370 throw new Error ( `Key with id ${ keyId } not found` ) ;
8471 }
8572
86- return Promise . resolve ( ( JSON . parse ( keyPair ) as JwkKeyPair ) . publicKey as Kms . KmsJwkPublic ) ;
73+ return ( JSON . parse ( keyPair ) as JwkKeyPair ) . publicKey as Kms . KmsJwkPublic ;
8774 }
8875 public async createKey < Type extends Kms . KmsCreateKeyType > ( agentContext : AgentContext , options : Kms . KmsCreateKeyOptions < Type > ) : Promise < Kms . KmsCreateKeyReturn < Type > > {
8976 options . keyId ??= "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" . replace ( / [ x y ] / g, function ( c ) {
@@ -122,13 +109,9 @@ export class EnmshedHolderKeyManagmentService implements Kms.KeyManagementServic
122109
123110 agentContext . config . logger . debug ( `EKM: Created EC key pair with id ${ options . keyId } ` ) ;
124111 // store the key pair in the keystore
125- this . keystore . set ( options . keyId , JSON . stringify ( jwkKeyPair ) ) ;
112+ await this . keyStorage . storeKey ( options . keyId , JSON . stringify ( jwkKeyPair ) ) ;
126113
127- this . updateGlobalInstance ( this . keystore ) ;
128- return await Promise . resolve ( {
129- keyId : options . keyId ,
130- publicJwk : publicJwk as Kms . KmsJwkPublic
131- } as Kms . KmsCreateKeyReturn < Type > ) ;
114+ return { keyId : options . keyId , publicJwk : publicJwk as Kms . KmsJwkPublic } as Kms . KmsCreateKeyReturn < Type > ;
132115 }
133116
134117 await _sodium . ready ;
@@ -157,31 +140,28 @@ export class EnmshedHolderKeyManagmentService implements Kms.KeyManagementServic
157140 keyType : "OKP"
158141 } ;
159142
160- // store the key pair in the keystore
161- this . keystore . set ( options . keyId , JSON . stringify ( jwkKeyPair ) ) ;
162- this . updateGlobalInstance ( this . keystore ) ;
163- return await Promise . resolve ( {
164- keyId : options . keyId ,
165- publicJwk : publicJwk as Kms . KmsJwkPublic
166- } as Kms . KmsCreateKeyReturn < Type > ) ;
143+ await this . keyStorage . storeKey ( options . keyId , JSON . stringify ( jwkKeyPair ) ) ;
144+ return { keyId : options . keyId , publicJwk : publicJwk as Kms . KmsJwkPublic } as Kms . KmsCreateKeyReturn < Type > ;
167145 }
146+
168147 public importKey < Jwk extends Kms . KmsJwkPrivate > ( agentContext : AgentContext , options : Kms . KmsImportKeyOptions < Jwk > ) : Promise < Kms . KmsImportKeyReturn < Jwk > > {
169148 agentContext . config . logger . debug ( `EKM: Importing key with ${ JSON . stringify ( options ) } ` ) ;
170149 throw new Error ( "Method not implemented." ) ;
171150 }
172- public deleteKey ( agentContext : AgentContext , options : Kms . KmsDeleteKeyOptions ) : Promise < boolean > {
173- if ( this . keystore . has ( options . keyId ) ) {
174- agentContext . config . logger . debug ( `EKM: Deleting key with id ${ options . keyId } ` ) ;
175- this . keystore . delete ( options . keyId ) ;
176- this . updateGlobalInstance ( this . keystore ) ;
177- return Promise . resolve ( true ) ;
178- }
179- throw new Error ( `key with id ${ options . keyId } not found. and cannot be deleted` ) ;
151+
152+ public async deleteKey ( agentContext : AgentContext , options : Kms . KmsDeleteKeyOptions ) : Promise < boolean > {
153+ const hasKey = await this . keyStorage . hasKey ( options . keyId ) ;
154+ if ( ! hasKey ) throw new Error ( `key with id ${ options . keyId } not found. and cannot be deleted` ) ;
155+
156+ agentContext . config . logger . debug ( `EKM: Deleting key with id ${ options . keyId } ` ) ;
157+ await this . keyStorage . deleteKey ( options . keyId ) ;
158+ return true ;
180159 }
160+
181161 public async sign ( agentContext : AgentContext , options : Kms . KmsSignOptions ) : Promise < Kms . KmsSignReturn > {
182162 agentContext . config . logger . debug ( `EKM: Signing data with key id ${ options . keyId } using algorithm ${ options . algorithm } ` ) ;
183163
184- const stringifiedKeyPair = this . keystore . get ( options . keyId ) ;
164+ const stringifiedKeyPair = await this . keyStorage . getKey ( options . keyId ) ;
185165 if ( ! stringifiedKeyPair ) {
186166 throw new Error ( `Key with id ${ options . keyId } not found` ) ;
187167 }
@@ -273,8 +253,8 @@ export class EnmshedHolderKeyManagmentService implements Kms.KeyManagementServic
273253 }
274254 }
275255
276- private ecdhEs ( localKeyId : string , remotePublicJWK : any ) : Uint8Array {
277- const keyPairString = this . keystore . get ( localKeyId ) ;
256+ private async ecdhEs ( localKeyId : string , remotePublicJWK : any ) : Promise < Uint8Array > {
257+ const keyPairString = await this . keyStorage . getKey ( localKeyId ) ;
278258 if ( ! keyPairString ) {
279259 throw new Error ( `Key with id ${ localKeyId } not found` ) ;
280260 }
@@ -360,7 +340,7 @@ export class EnmshedHolderKeyManagmentService implements Kms.KeyManagementServic
360340 return hashBuf . subarray ( 0 , keyLength / 8 ) ;
361341 }
362342
363- public encrypt ( agentContext : AgentContext , options : Kms . KmsEncryptOptions ) : Promise < Kms . KmsEncryptReturn > {
343+ public async encrypt ( agentContext : AgentContext , options : Kms . KmsEncryptOptions ) : Promise < Kms . KmsEncryptReturn > {
364344 try {
365345 // encryption via A-256-GCM
366346 // we will call the services side bob and the incoming side alice
@@ -372,7 +352,7 @@ export class EnmshedHolderKeyManagmentService implements Kms.KeyManagementServic
372352 }
373353
374354 // 1. derive the shared secret via ECDH-ES
375- const sharedSecret = this . ecdhEs ( options . key . keyAgreement . keyId , options . key . keyAgreement . externalPublicJwk ) ;
355+ const sharedSecret = await this . ecdhEs ( options . key . keyAgreement . keyId , options . key . keyAgreement . externalPublicJwk ) ;
376356 agentContext . config . logger . debug ( `EKM: Derived shared secret for encryption using ECDH-ES` ) ;
377357 // 2. Concat KDF to form the final key
378358 const derivedKey = this . concatKdf ( sharedSecret , 256 , "A256GCM" , options . key . keyAgreement ) ;
@@ -403,7 +383,7 @@ export class EnmshedHolderKeyManagmentService implements Kms.KeyManagementServic
403383 tag : tag
404384 } ;
405385
406- return Promise . resolve ( returnValue ) ;
386+ return returnValue ;
407387 } catch ( e ) {
408388 agentContext . config . logger . error ( `EKM: Error during encryption: ${ e } ` ) ;
409389 throw e ;
0 commit comments