1
1
import { IKeyProvider } from '../kms' ;
2
2
import { AbstractPrivateKeyStore , KmsKeyId , KmsKeyType } from '../store' ;
3
- import Elliptic from 'elliptic' ;
4
3
import * as providerHelpers from '../provider-helpers' ;
5
- import { ES256KSigner } from 'did-jwt' ;
6
- import { base64UrlToBytes , byteEncoder , bytesToHex , hexToBytes } from '../../utils' ;
4
+ import { base64UrlToBytes , bytesToHex } from '../../utils' ;
5
+ import { secp256k1 } from '@noble/curves/secp256k1' ;
6
+ import { sha256 } from '@iden3/js-crypto' ;
7
+ import { ES256KSigner , hexToBytes } from 'did-jwt' ;
7
8
8
9
/**
9
- * Provider for Sec256p1 keys256p1
10
+ * Provider for Secp256k1
10
11
* @public
11
- * @class Sec256p1Provider
12
+ * @class Secp256k1Provider
12
13
* @implements implements IKeyProvider interface
13
14
*/
14
15
export class Sec256k1Provider implements IKeyProvider {
@@ -19,16 +20,17 @@ export class Sec256k1Provider implements IKeyProvider {
19
20
keyType : KmsKeyType ;
20
21
private _keyStore : AbstractPrivateKeyStore ;
21
22
22
- private readonly _ec ;
23
23
/**
24
24
* Creates an instance of BjjProvider.
25
25
* @param {KmsKeyType } keyType - kms key type
26
26
* @param {AbstractPrivateKeyStore } keyStore - key store for kms
27
27
*/
28
28
constructor ( keyType : KmsKeyType , keyStore : AbstractPrivateKeyStore ) {
29
+ if ( keyType !== KmsKeyType . Secp256k1 ) {
30
+ throw new Error ( 'Key type must be Secp256k1' ) ;
31
+ }
29
32
this . keyType = keyType ;
30
33
this . _keyStore = keyStore ;
31
- this . _ec = new Elliptic . ec ( 'secp256k1' ) ;
32
34
}
33
35
/**
34
36
* generates a baby jub jub key from a seed phrase
@@ -39,14 +41,15 @@ export class Sec256k1Provider implements IKeyProvider {
39
41
if ( seed . length !== 32 ) {
40
42
throw new Error ( 'Seed should be 32 bytes' ) ;
41
43
}
42
- const keyPair = this . _ec . keyFromPrivate ( seed ) ;
44
+ const publicKey = secp256k1 . getPublicKey ( seed ) ;
43
45
const kmsId = {
44
46
type : this . keyType ,
45
- id : providerHelpers . keyPath ( this . keyType , keyPair . getPublic ( ) . encode ( 'hex' , false ) )
47
+ id : providerHelpers . keyPath ( this . keyType , bytesToHex ( publicKey ) )
46
48
} ;
49
+
47
50
await this . _keyStore . importKey ( {
48
51
alias : kmsId . id ,
49
- key : keyPair . getPrivate ( ) . toString ( 'hex' ) . padStart ( 64 , '0' )
52
+ key : bytesToHex ( seed ) . padStart ( 64 , '0' )
50
53
} ) ;
51
54
52
55
return kmsId ;
@@ -59,37 +62,46 @@ export class Sec256k1Provider implements IKeyProvider {
59
62
*/
60
63
async publicKey ( keyId : KmsKeyId ) : Promise < string > {
61
64
const privateKeyHex = await this . privateKey ( keyId ) ;
62
- return this . _ec . keyFromPrivate ( privateKeyHex , 'hex' ) . getPublic ( ) . encode ( 'hex' , false ) ; // 04 + x + y (uncompressed key)
65
+ const publicKey = secp256k1 . getPublicKey ( privateKeyHex , false ) ; // 04 + x + y (uncompressed key)
66
+ return bytesToHex ( publicKey ) ;
63
67
}
64
68
65
69
/**
66
- * signs prepared payload of size,
67
- * with a key id
68
- *
69
- * @param {KmsKeyId } keyId - key identifier
70
- * @param {Uint8Array } data - data to sign (32 bytes)
71
- * @returns Uint8Array signature
70
+ * Signs the given data using the private key associated with the specified key identifier.
71
+ * @param keyId - The key identifier to use for signing.
72
+ * @param data - The data to sign.
73
+ * @param opts - Signing options, such as the algorithm to use.
74
+ * @returns A Promise that resolves to the signature as a Uint8Array.
72
75
*/
73
76
async sign (
74
77
keyId : KmsKeyId ,
75
78
data : Uint8Array ,
76
79
opts : { [ key : string ] : unknown } = { alg : 'ES256K' }
77
80
) : Promise < Uint8Array > {
78
81
const privateKeyHex = await this . privateKey ( keyId ) ;
79
- if ( ! privateKeyHex ) {
80
- throw new Error ( 'Private key not found for keyId: ' + keyId . id ) ;
81
- }
82
+
82
83
const signatureBase64 = await ES256KSigner (
83
84
hexToBytes ( privateKeyHex ) ,
84
85
opts . alg === 'ES256K-R'
85
86
) ( data ) ;
86
87
87
- const signatureHex = bytesToHex ( base64UrlToBytes ( signatureBase64 . toString ( ) ) ) ;
88
- if ( typeof signatureHex !== 'string' ) {
89
- throw new Error ( 'Signature is not a string' ) ;
88
+ if ( typeof signatureBase64 !== 'string' ) {
89
+ throw new Error ( 'signatureBase64 must be a string' ) ;
90
90
}
91
91
92
- return byteEncoder . encode ( signatureBase64 . toString ( ) ) ;
92
+ return base64UrlToBytes ( signatureBase64 ) ;
93
+ }
94
+
95
+ /**
96
+ * Verifies a signature for the given message and key identifier.
97
+ * @param message - The message to verify the signature against.
98
+ * @param signatureHex - The signature to verify, as a hexadecimal string.
99
+ * @param keyId - The key identifier to use for verification.
100
+ * @returns A Promise that resolves to a boolean indicating whether the signature is valid.
101
+ */
102
+ async verify ( message : Uint8Array , signatureHex : string , keyId : KmsKeyId ) : Promise < boolean > {
103
+ const publicKeyHex = await this . publicKey ( keyId ) ;
104
+ return secp256k1 . verify ( signatureHex , sha256 ( message ) , publicKeyHex ) ;
93
105
}
94
106
95
107
private async privateKey ( keyId : KmsKeyId ) : Promise < string > {
0 commit comments