1+ import { CONFIG } from '../config'
12import { makeLocalFileFetch } from '../file-fetch'
23import { makeGnarkOPRFOperator } from '../gnark/toprf'
34import { strToUint8Array } from '../gnark/utils'
4- import { OPRFResponseData , ZKTOPRFPublicSignals } from '../types'
5+ import { EncryptionAlgorithm , OPRFOperator , OPRFResponseData , ZKEngine , ZKTOPRFPublicSignals } from '../types'
56import { generateProof , verifyProof } from '../zk'
67import { encryptData } from './utils'
78
89const fetcher = makeLocalFileFetch ( )
9- const operator = makeGnarkOPRFOperator ( { fetcher, algorithm : 'chacha20' } )
1010const threshold = 1
1111
1212const POSITIONS = [
1313 0 ,
1414 10
1515]
1616
17- describe ( 'TOPRF circuits Tests' , ( ) => {
17+ type Config = {
18+ make : ( alg : EncryptionAlgorithm ) => OPRFOperator
19+ algorithms : EncryptionAlgorithm [ ]
20+ }
1821
19- it . each ( POSITIONS ) ( 'should prove & verify TOPRF at pos=%s' , async pos => {
20- 21- const domainSeparator = 'reclaim'
22+ const OPRF_ZK_ENGINES_MAP : { [ E in ZKEngine ] ?: Config } = {
23+ 'gnark' : {
24+ make : algorithm => makeGnarkOPRFOperator ( { fetcher, algorithm } ) ,
25+ algorithms : [ 'chacha20' , 'aes-128-ctr' , 'aes-256-ctr' ] ,
26+ }
27+ }
2228
23- const keys = await operator . generateThresholdKeys ( 5 , threshold )
24- const req = await operator
25- . generateOPRFRequestData ( strToUint8Array ( email ) , domainSeparator )
29+ const OPRF_ENGINES = Object . keys ( OPRF_ZK_ENGINES_MAP ) as ZKEngine [ ]
2630
27- const resps : OPRFResponseData [ ] = [ ]
28- for ( let i = 0 ; i < threshold ; i ++ ) {
29- const evalResult = await operator . evaluateOPRF (
30- keys . shares [ i ] . privateKey ,
31- req . maskedData
32- )
31+ describe . each ( OPRF_ENGINES ) ( '%s TOPRF circuits Tests' , engine => {
3332
34- resps . push ( {
35- publicKeyShare : keys . shares [ i ] . publicKey ,
36- evaluated : evalResult . evaluated ,
37- c : evalResult . c ,
38- r : evalResult . r ,
39- } )
40- }
41-
42- const nullifier = await operator
43- . finaliseOPRF ( keys . publicKey , req , resps )
44- const len = email . length
45-
46- const plaintext = new Uint8Array ( Buffer . alloc ( 64 ) )
47- //replace part of plaintext with email
48- plaintext . set ( new Uint8Array ( Buffer . from ( email ) ) , pos )
49-
50- const key = new Uint8Array ( Array . from ( Array ( 32 ) . keys ( ) ) )
51- const iv = new Uint8Array ( Array . from ( Array ( 12 ) . keys ( ) ) )
52-
53- const ciphertext = encryptData ( 'chacha20' , plaintext , key , iv )
54-
55- const toprf : ZKTOPRFPublicSignals = {
56- pos : pos , //pos in plaintext
57- len : len , // length of data to "hash"
58- domainSeparator,
59- output : nullifier ,
60- responses : resps
61- }
62-
63- const proof = await generateProof ( {
64- algorithm : 'chacha20' ,
65- privateInput : {
66- key,
67- } ,
68- publicInput : {
69- iv,
70- ciphertext,
71- offset : 0
72- } ,
73- operator,
74- mask : req . mask ,
75- toprf,
76- } )
33+ const { make, algorithms } = OPRF_ZK_ENGINES_MAP [ engine ] !
34+
35+ describe . each ( algorithms ) ( '%s' , algorithm => {
36+
37+ const operator = make ( algorithm )
38+
39+ it . each ( POSITIONS ) ( 'should prove & verify TOPRF at pos=%s' , async pos => {
40+ 41+ const domainSeparator = 'reclaim'
42+
43+ const keys = await operator . generateThresholdKeys ( 5 , threshold )
44+ const req = await operator
45+ . generateOPRFRequestData ( strToUint8Array ( email ) , domainSeparator )
46+
47+ const resps : OPRFResponseData [ ] = [ ]
48+ for ( let i = 0 ; i < threshold ; i ++ ) {
49+ const evalResult = await operator . evaluateOPRF (
50+ keys . shares [ i ] . privateKey ,
51+ req . maskedData
52+ )
53+
54+ resps . push ( {
55+ publicKeyShare : keys . shares [ i ] . publicKey ,
56+ evaluated : evalResult . evaluated ,
57+ c : evalResult . c ,
58+ r : evalResult . r ,
59+ } )
60+ }
7761
78- await expect (
79- verifyProof ( {
80- proof,
62+ const nullifier = await operator
63+ . finaliseOPRF ( keys . publicKey , req , resps )
64+ const len = email . length
65+
66+ const plaintext = new Uint8Array ( Buffer . alloc ( 64 ) )
67+ //replace part of plaintext with email
68+ plaintext . set ( new Uint8Array ( Buffer . from ( email ) ) , pos )
69+
70+ const { keySizeBytes } = CONFIG [ algorithm ]
71+ const key = new Uint8Array ( Array . from ( Array ( keySizeBytes ) . keys ( ) ) )
72+ const iv = new Uint8Array ( Array . from ( Array ( 12 ) . keys ( ) ) )
73+
74+ const ciphertext = encryptData ( algorithm , plaintext , key , iv )
75+
76+ const toprf : ZKTOPRFPublicSignals = {
77+ pos : pos , //pos in plaintext
78+ len : len , // length of data to "hash"
79+ domainSeparator,
80+ output : nullifier ,
81+ responses : resps
82+ }
83+
84+ const proof = await generateProof ( {
85+ algorithm,
86+ privateInput : {
87+ key,
88+ } ,
8189 publicInput : {
8290 iv,
8391 ciphertext,
8492 offset : 0
8593 } ,
94+ operator,
95+ mask : req . mask ,
8696 toprf,
87- operator
8897 } )
89- ) . resolves . toBeUndefined ( )
98+
99+ await expect (
100+ verifyProof ( {
101+ proof,
102+ publicInput : { iv, ciphertext,
103+ offset : 0
104+ } ,
105+ toprf,
106+ operator
107+ } )
108+ ) . resolves . toBeUndefined ( )
109+ } )
90110 } )
91111} )
0 commit comments