@@ -54,6 +54,14 @@ const modN = (n: bigint) => mod(n, CURVE_ORDER);
54
54
// - https://strobe.sourceforge.io/specs/
55
55
// We can implement full version, but seems nobody uses this much.
56
56
const STROBE_R : number = 166 ;
57
+ // const Flags2 = {
58
+ // I: 1,
59
+ // A: 1 << 1,
60
+ // C: 1 << 2,
61
+ // T: 1 << 3,
62
+ // M: 1 << 4,
63
+ // K: 1 << 5,
64
+ // } as const;
57
65
const enum Flags {
58
66
I = 1 ,
59
67
A = 1 << 1 ,
@@ -65,7 +73,7 @@ const enum Flags {
65
73
// TODO: this is very close to KeccakPRG, try to merge?
66
74
// Differences: suffix, additional methods/flags
67
75
export class Strobe128 {
68
- state = new Uint8Array ( 200 ) ;
76
+ state : Uint8Array = new Uint8Array ( 200 ) ;
69
77
state32 : Uint32Array ;
70
78
pos : number = 0 ;
71
79
posBegin : number = 0 ;
@@ -148,7 +156,7 @@ export class Strobe128 {
148
156
this . overwrite ( toData ( data ) ) ;
149
157
}
150
158
// Utils
151
- clone ( ) {
159
+ clone ( ) : Strobe128 {
152
160
const n = new Strobe128 ( '0' ) ; // tmp
153
161
n . pos = this . pos ;
154
162
n . posBegin = this . posBegin ;
@@ -167,15 +175,15 @@ export class Merlin {
167
175
this . strobe = new Strobe128 ( 'Merlin v1.0' ) ;
168
176
this . appendMessage ( 'dom-sep' , label ) ;
169
177
}
170
- appendMessage ( label : Data , message : Data ) {
178
+ appendMessage ( label : Data , message : Data ) : void {
171
179
this . strobe . metaAD ( label , false ) ;
172
180
this . strobe . metaAD ( numberToBytesLE ( message . length , 4 ) , true ) ;
173
181
this . strobe . AD ( message , false ) ;
174
182
}
175
- appendU64 ( label : Data , n : number | bigint ) {
183
+ appendU64 ( label : Data , n : number | bigint ) : void {
176
184
this . appendMessage ( label , numberToBytesLE ( n , 8 ) ) ;
177
185
}
178
- challengeBytes ( label : Data , len : number ) {
186
+ challengeBytes ( label : Data , len : number ) : Uint8Array {
179
187
this . strobe . metaAD ( label , false ) ;
180
188
this . strobe . metaAD ( numberToBytesLE ( len , 4 ) , true ) ;
181
189
return this . strobe . PRF ( len , false ) ;
@@ -190,26 +198,26 @@ export class SigningContext extends Merlin {
190
198
) {
191
199
super ( name ) ;
192
200
}
193
- label ( label : Data ) {
201
+ label ( label : Data ) : void {
194
202
this . appendMessage ( '' , label ) ;
195
203
}
196
- bytes ( bytes : Uint8Array ) {
204
+ bytes ( bytes : Uint8Array ) : this {
197
205
this . appendMessage ( 'sign-bytes' , bytes ) ;
198
206
return this ;
199
207
}
200
- protoName ( label : Data ) {
208
+ protoName ( label : Data ) : void {
201
209
this . appendMessage ( 'proto-name' , label ) ;
202
210
}
203
- commitPoint ( label : Data , point : Point ) {
211
+ commitPoint ( label : Data , point : Point ) : void {
204
212
this . appendMessage ( label , point . toRawBytes ( ) ) ;
205
213
}
206
214
challengeScalar ( label : Data ) : bigint {
207
215
return modN ( bytesToNumberLE ( this . challengeBytes ( label , 64 ) ) ) ;
208
216
}
209
- witnessScalar ( label : Data , nonceSeeds : Uint8Array [ ] = [ ] ) {
217
+ witnessScalar ( label : Data , nonceSeeds : Uint8Array [ ] = [ ] ) : bigint {
210
218
return modN ( bytesToNumberLE ( this . witnessBytes ( label , 64 , nonceSeeds ) ) ) ;
211
219
}
212
- witnessBytes ( label : Data , len : number , nonceSeeds : Uint8Array [ ] = [ ] ) {
220
+ witnessBytes ( label : Data , len : number , nonceSeeds : Uint8Array [ ] = [ ] ) : Uint8Array {
213
221
const strobeRng = this . strobe . clone ( ) ;
214
222
for ( const ns of nonceSeeds ) {
215
223
strobeRng . metaAD ( label , false ) ;
@@ -232,7 +240,7 @@ const encodeScalar = (n: bigint) => numberToBytesLE((n << _3n) & MASK, 32);
232
240
const decodeScalar = ( n : Uint8Array ) => bytesToNumberLE ( n ) >> _3n ;
233
241
234
242
// NOTE: secretKey is 64 bytes (key + nonce). This required for HDKD, since key can be derived not only from seed, but from other keys.
235
- export function getPublicKey ( secretKey : Uint8Array ) {
243
+ export function getPublicKey ( secretKey : Uint8Array ) : Uint8Array {
236
244
abytes ( 'secretKey' , secretKey , 64 ) ;
237
245
const scalar = decodeScalar ( secretKey . subarray ( 0 , 32 ) ) ;
238
246
return RistrettoPoint . BASE . multiply ( scalar ) . toRawBytes ( ) ;
@@ -251,7 +259,7 @@ export function secretFromSeed(seed: Uint8Array): Uint8Array {
251
259
}
252
260
// Seems like ed25519 keypair? Generates keypair from other keypair in ed25519 format
253
261
// NOTE: not exported from wasm. Do we need this at all?
254
- export function fromKeypair ( pair : Uint8Array ) {
262
+ export function fromKeypair ( pair : Uint8Array ) : Uint8Array {
255
263
abytes ( 'keypair' , pair , 96 ) ;
256
264
const sk = pair . slice ( 0 , 32 ) ;
257
265
const nonce = pair . slice ( 32 , 64 ) ;
@@ -264,7 +272,11 @@ export function fromKeypair(pair: Uint8Array) {
264
272
265
273
// Basic sign. NOTE: context is currently constant. Please open issue if you need different one.
266
274
const SUBSTRATE_CONTEXT = utf8ToBytes ( 'substrate' ) ;
267
- export function sign ( secretKey : Uint8Array , message : Uint8Array , rng = randomBytes ) {
275
+ export function sign (
276
+ secretKey : Uint8Array ,
277
+ message : Uint8Array ,
278
+ rng : typeof randomBytes = randomBytes
279
+ ) : Uint8Array {
268
280
abytes ( 'message' , message ) ;
269
281
abytes ( 'secretKey' , secretKey , 64 ) ;
270
282
const t = new SigningContext ( 'SigningContext' , rng ) ;
@@ -284,7 +296,7 @@ export function sign(secretKey: Uint8Array, message: Uint8Array, rng = randomByt
284
296
res [ 63 ] |= 128 ; // add Schnorrkel marker
285
297
return res ;
286
298
}
287
- export function verify ( message : Uint8Array , signature : Uint8Array , publicKey : Uint8Array ) {
299
+ export function verify ( message : Uint8Array , signature : Uint8Array , publicKey : Uint8Array ) : boolean {
288
300
abytes ( 'message' , message ) ;
289
301
abytes ( 'signature' , signature , 64 ) ;
290
302
abytes ( 'publicKey' , publicKey , 32 ) ;
@@ -306,7 +318,7 @@ export function verify(message: Uint8Array, signature: Uint8Array, publicKey: Ui
306
318
const RR = pubPoint . negate ( ) . multiply ( k ) . add ( sP ) ;
307
319
return RR . equals ( R ) ;
308
320
}
309
- export function getSharedSecret ( secretKey : Uint8Array , publicKey : Uint8Array ) {
321
+ export function getSharedSecret ( secretKey : Uint8Array , publicKey : Uint8Array ) : Uint8Array {
310
322
abytes ( 'secretKey' , secretKey , 64 ) ;
311
323
abytes ( 'publicKey' , publicKey , 32 ) ;
312
324
const keyScalar = decodeScalar ( secretKey . subarray ( 0 , 32 ) ) ;
@@ -316,7 +328,11 @@ export function getSharedSecret(secretKey: Uint8Array, publicKey: Uint8Array) {
316
328
317
329
// Derive
318
330
export const HDKD = {
319
- secretSoft ( secretKey : Uint8Array , chainCode : Uint8Array , rng = randomBytes ) {
331
+ secretSoft (
332
+ secretKey : Uint8Array ,
333
+ chainCode : Uint8Array ,
334
+ rng : typeof randomBytes = randomBytes
335
+ ) : Uint8Array {
320
336
abytes ( 'secretKey' , secretKey , 64 ) ;
321
337
abytes ( 'chainCode' , chainCode , 32 ) ;
322
338
const masterScalar = decodeScalar ( secretKey . subarray ( 0 , 32 ) ) ;
@@ -335,7 +351,7 @@ export const HDKD = {
335
351
const key = encodeScalar ( modN ( masterScalar + scalar ) ) ;
336
352
return concatBytes ( key , nonce ) ;
337
353
} ,
338
- publicSoft ( publicKey : Uint8Array , chainCode : Uint8Array ) {
354
+ publicSoft ( publicKey : Uint8Array , chainCode : Uint8Array ) : Uint8Array {
339
355
abytes ( 'publicKey' , publicKey , 32 ) ;
340
356
abytes ( 'chainCode' , chainCode , 32 ) ;
341
357
const pubPoint = RistrettoPoint . fromHex ( publicKey ) ;
@@ -347,7 +363,7 @@ export const HDKD = {
347
363
t . challengeBytes ( 'HDKD-chaincode' , 32 ) ;
348
364
return pubPoint . add ( RistrettoPoint . BASE . multiply ( scalar ) ) . toRawBytes ( ) ;
349
365
} ,
350
- secretHard ( secretKey : Uint8Array , chainCode : Uint8Array ) {
366
+ secretHard ( secretKey : Uint8Array , chainCode : Uint8Array ) : Uint8Array {
351
367
abytes ( 'secretKey' , secretKey , 64 ) ;
352
368
abytes ( 'chainCode' , chainCode , 32 ) ;
353
369
const key = numberToBytesLE ( decodeScalar ( secretKey . subarray ( 0 , 32 ) ) , 32 ) ;
@@ -416,7 +432,13 @@ function initVRF(
416
432
return { input, t : transcript } ;
417
433
}
418
434
export const vrf = {
419
- sign ( msg : Uint8Array , secretKey : Uint8Array , ctx = EMPTY , extra = EMPTY , rng = randomBytes ) {
435
+ sign (
436
+ msg : Uint8Array ,
437
+ secretKey : Uint8Array ,
438
+ ctx : Uint8Array = EMPTY ,
439
+ extra : Uint8Array = EMPTY ,
440
+ rng : typeof randomBytes = randomBytes
441
+ ) : Uint8Array {
420
442
abytes ( 'msg' , msg ) ;
421
443
abytes ( 'secretKey' , secretKey , 64 ) ;
422
444
abytes ( 'ctx' , ctx ) ;
@@ -438,10 +460,10 @@ export const vrf = {
438
460
msg : Uint8Array ,
439
461
signature : Uint8Array ,
440
462
publicKey : Uint8Array ,
441
- ctx = EMPTY ,
442
- extra = EMPTY ,
443
- rng = randomBytes
444
- ) {
463
+ ctx : Uint8Array = EMPTY ,
464
+ extra : Uint8Array = EMPTY ,
465
+ rng : typeof randomBytes = randomBytes
466
+ ) : boolean {
445
467
abytes ( 'msg' , msg ) ;
446
468
abytes ( 'signature' , signature , 96 ) ; // O(point) || c(scalar) || s(scalar)
447
469
abytes ( 'pubkey' , publicKey , 32 ) ;
@@ -462,7 +484,11 @@ export const vrf = {
462
484
} ;
463
485
464
486
// NOTE: for tests only, don't use
465
- export const __tests = {
487
+ export const __tests : {
488
+ Strobe128 : typeof Strobe128 ;
489
+ Merlin : typeof Merlin ;
490
+ SigningContext : typeof SigningContext ;
491
+ } = {
466
492
Strobe128,
467
493
Merlin,
468
494
SigningContext,
0 commit comments