1
- import { IBls } from "./types.js" ;
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import * as blst from "@chainsafe/blst-ts" ;
3
+ import { IBls , PublicKey , PublicKeyArg , Signature , SignatureArg } from "./types.js" ;
2
4
import { validateBytes } from "./helpers/index.js" ;
3
- import { NotInitializedError } from "./errors.js" ;
5
+ import { NotInitializedError , ZeroSignatureError } from "./errors.js" ;
4
6
5
7
// Returned type is enforced at each implementation's index
6
8
// eslint-disable-next-line max-len
7
9
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type,@typescript-eslint/explicit-module-boundary-types
8
10
export function functionalInterfaceFactory ( {
11
+ implementation,
9
12
SecretKey,
10
13
PublicKey,
11
14
Signature,
12
- } : Pick < IBls , "SecretKey" | "PublicKey" | "Signature" > ) {
15
+ } : Pick < IBls , "implementation" | " SecretKey" | "PublicKey" | "Signature" > ) {
13
16
/**
14
17
* Signs given message using secret key.
15
18
* @param secretKey
@@ -47,9 +50,11 @@ export function functionalInterfaceFactory({
47
50
* @param signature
48
51
*/
49
52
function verify ( publicKey : Uint8Array , message : Uint8Array , signature : Uint8Array ) : boolean {
50
- validateBytes ( publicKey , "publicKey" ) ;
51
- validateBytes ( message , "message" ) ;
52
- validateBytes ( signature , "signature" ) ;
53
+ if ( implementation === "herumi" ) {
54
+ validateBytes ( publicKey , "publicKey" ) ;
55
+ validateBytes ( message , "message" ) ;
56
+ validateBytes ( signature , "signature" ) ;
57
+ }
53
58
54
59
try {
55
60
return Signature . fromBytes ( signature ) . verify ( PublicKey . fromBytes ( publicKey ) , message ) ;
@@ -58,6 +63,27 @@ export function functionalInterfaceFactory({
58
63
return false ;
59
64
}
60
65
}
66
+ async function asyncVerify ( message : Uint8Array , publicKey : PublicKeyArg , signature : SignatureArg ) : Promise < boolean > {
67
+ if ( implementation === "herumi" ) {
68
+ throw new Error ( "WASM implementation does not support asyncVerify, use verify instead" ) ;
69
+ }
70
+
71
+ const pk = publicKey instanceof PublicKey ? ( ( publicKey as any ) . key as blst . PublicKey ) : publicKey ;
72
+ const sig =
73
+ signature instanceof Signature
74
+ ? ( ( signature as any ) . sig as blst . Signature )
75
+ : blst . Signature . deserialize ( signature ) ;
76
+
77
+ if ( sig . isInfinity ( ) ) {
78
+ false ;
79
+ }
80
+
81
+ try {
82
+ return blst . asyncVerify ( message , pk , sig ) ;
83
+ } catch {
84
+ return false ;
85
+ }
86
+ }
61
87
62
88
/**
63
89
* Verifies if aggregated signature is same message signed with given public keys.
@@ -80,6 +106,26 @@ export function functionalInterfaceFactory({
80
106
return false ;
81
107
}
82
108
}
109
+ async function asyncVerifyAggregate (
110
+ message : Uint8Array ,
111
+ publicKeys : PublicKeyArg [ ] ,
112
+ signature : SignatureArg
113
+ ) : Promise < boolean > {
114
+ if ( implementation === "herumi" ) {
115
+ throw new Error ( "WASM implementation does not support asyncVerifyAggregate, use verifyAggregate instead" ) ;
116
+ }
117
+
118
+ const pks = publicKeys . map ( ( pk ) => ( pk instanceof PublicKey ? ( ( pk as any ) . key as blst . PublicKey ) : pk ) ) ;
119
+ const sig = signature instanceof Signature ? ( ( signature as any ) . sig as blst . Signature ) : signature ;
120
+
121
+ // TODO: (matthewkeil) check spec to make sure this sig does not need inf check
122
+
123
+ try {
124
+ return blst . fastAggregateVerify ( message , pks , sig ) ;
125
+ } catch {
126
+ return false ;
127
+ }
128
+ }
83
129
84
130
/**
85
131
* Verifies if signature is list of message signed with corresponding public key.
@@ -106,6 +152,30 @@ export function functionalInterfaceFactory({
106
152
return false ;
107
153
}
108
154
}
155
+ async function asyncVerifyMultiple (
156
+ messages : Uint8Array [ ] ,
157
+ publicKeys : PublicKeyArg [ ] ,
158
+ signature : SignatureArg
159
+ ) : Promise < boolean > {
160
+ if ( implementation === "herumi" ) {
161
+ throw new Error ( "WASM implementation does not support asyncVerifyMultiple, use verifyMultiple instead" ) ;
162
+ }
163
+
164
+ if ( publicKeys . length === 0 || publicKeys . length != messages . length ) {
165
+ return false ;
166
+ }
167
+
168
+ const pks = publicKeys . map ( ( pk ) => ( pk instanceof PublicKey ? ( ( pk as any ) . key as blst . PublicKey ) : pk ) ) ;
169
+ const sig = signature instanceof Signature ? ( ( signature as any ) . sig as blst . Signature ) : signature ;
170
+
171
+ // TODO: (matthewkeil) check spec to make sure this sig does not need inf check
172
+
173
+ try {
174
+ return blst . aggregateVerify ( messages , pks , sig ) ;
175
+ } catch {
176
+ return false ;
177
+ }
178
+ }
109
179
110
180
/**
111
181
* Verifies multiple signatures at once returning true if all valid or false
@@ -135,6 +205,25 @@ export function functionalInterfaceFactory({
135
205
return false ;
136
206
}
137
207
}
208
+ async function asyncVerifyMultipleSignatures (
209
+ sets : { message : Uint8Array ; publicKey : PublicKeyArg ; signature : SignatureArg } [ ]
210
+ ) : Promise < boolean > {
211
+ if ( ! sets ) throw Error ( "sets is null or undefined" ) ;
212
+
213
+ try {
214
+ return blst . asyncVerifyMultipleAggregateSignatures (
215
+ sets . map ( ( set ) => ( {
216
+ message : set . message ,
217
+ publicKey :
218
+ set . publicKey instanceof PublicKey ? ( ( set . publicKey as any ) . key as blst . PublicKey ) : set . publicKey ,
219
+ signature :
220
+ set . signature instanceof Signature ? ( ( set . signature as any ) . sig as blst . Signature ) : set . signature ,
221
+ } ) )
222
+ ) ;
223
+ } catch {
224
+ return false ;
225
+ }
226
+ }
138
227
139
228
/**
140
229
* Computes a public key from a secret key
@@ -152,6 +241,10 @@ export function functionalInterfaceFactory({
152
241
verifyAggregate,
153
242
verifyMultiple,
154
243
verifyMultipleSignatures,
244
+ asyncVerify,
245
+ asyncVerifyAggregate,
246
+ asyncVerifyMultiple,
247
+ asyncVerifyMultipleSignatures,
155
248
secretKeyToPublicKey,
156
249
} ;
157
250
}
0 commit comments