@@ -95,11 +95,164 @@ def _gen_ed25519():
95
95
print (r"};" )
96
96
97
97
98
+ @dataclass
99
+ class XDHVerify :
100
+ tcId : int
101
+ comment : str
102
+ shared : bytes
103
+ prv : bytes
104
+ pub : bytes
105
+ ok : bool
106
+
107
+ def _gen_x25519 ():
108
+ req = requests .get (
109
+ "https://raw.githubusercontent.com/google/wycheproof/master/testvectors/x25519_test.json"
110
+ )
111
+ assert req .status_code == 200
112
+ file = req .json ()
113
+ assert file ["algorithm" ] == "XDH"
114
+ assert file ["schema" ] == "xdh_comp_schema.json"
115
+ verify_tests = []
116
+ for group in file ["testGroups" ]:
117
+ if group ["type" ] != "XdhComp" :
118
+ print (f"Skipping { group ['type' ]} test" , file = sys .stderr )
119
+ continue
120
+ for test in group ["tests" ]:
121
+ verify_tests .append (
122
+ XDHVerify (
123
+ tcId = test ["tcId" ],
124
+ comment = test ["comment" ],
125
+ shared = bytes .fromhex (test ["shared" ]),
126
+ prv = bytes .fromhex (test ["private" ]),
127
+ pub = bytes .fromhex (test ["public" ]),
128
+ ok = "ZeroSharedSecret" not in set (test ["flags" ]),
129
+ )
130
+ )
131
+
132
+ print ("/* Code generated by gen_wycheproofs.py. DO NOT EDIT. */" )
133
+ print (
134
+ f"/* Generated at { datetime .datetime .now (datetime .timezone .utc ).isoformat ()} */"
135
+ )
136
+ print (
137
+ """
138
+ #include "../fd_ballet_base.h"
139
+
140
+ struct fd_x25519_verify_wycheproof {
141
+ char const * comment;
142
+ uchar shared[32];
143
+ uchar prv[32];
144
+ uchar pub[32];
145
+ uint tc_id;
146
+ int ok;
147
+ };
148
+
149
+ typedef struct fd_x25519_verify_wycheproof fd_x25519_verify_wycheproof_t;
150
+
151
+ static fd_x25519_verify_wycheproof_t const x25519_verify_wycheproofs[] = {"""
152
+ )
153
+
154
+ for test in verify_tests :
155
+ print (f" {{ .tc_id = { test .tcId } ," )
156
+ print (f' .comment = "{ test .comment } ",' )
157
+ print (
158
+ r' .shared = "' + "" .join ([r"\x%02x" % (x ) for x in test .shared ]) + r'",'
159
+ )
160
+ print (
161
+ r' .prv = "' + "" .join ([r"\x%02x" % (x ) for x in test .prv ]) + r'",'
162
+ )
163
+ print (
164
+ r' .pub = "' + "" .join ([r"\x%02x" % (x ) for x in test .pub ]) + r'",'
165
+ )
166
+ print (f" .ok = { 1 if test .ok else 0 } }}," )
167
+
168
+ print (r" {0}" )
169
+ print (r"};" )
170
+
171
+
172
+ def _gen_cctv_ed25519 ():
173
+ req = requests .get (
174
+ "https://raw.githubusercontent.com/C2SP/CCTV/main/ed25519/ed25519vectors.json"
175
+ )
176
+ assert req .status_code == 200
177
+ file = req .json ()
178
+ verify_tests = []
179
+ for test in file :
180
+ flags = test ["flags" ]
181
+ if flags :
182
+ set_flags = set (flags )
183
+ ok = not (flags ) or set_flags == set (["low_order_component_A" ]) or set_flags == set (["low_order_component_A" , "low_order_component_R" ])
184
+ if "non_canonical_R" in set_flags and "low_order_R" not in set_flags :
185
+ raise Exception (test ["number" ])
186
+ else :
187
+ ok = True
188
+ verify_tests .append (
189
+ EddsaVerify (
190
+ tcId = test ["number" ],
191
+ comment = test ["msg" ],
192
+ msg = bytes (test ["msg" ], 'utf-8' ),
193
+ sig = bytes .fromhex (test ["sig" ]),
194
+ pub = bytes .fromhex (test ["key" ]),
195
+ ok = ok , # we implement dalek verify_strict, so all these should fail
196
+ )
197
+ )
198
+
199
+ print ("/* Code generated by gen_wycheproofs.py. DO NOT EDIT. */" )
200
+ print (
201
+ f"/* Generated at { datetime .datetime .now (datetime .timezone .utc ).isoformat ()} */"
202
+ )
203
+ print (
204
+ """
205
+ #include "../fd_ballet_base.h"
206
+
207
+ struct fd_ed25519_verify_cctv {
208
+ char const * comment;
209
+ uchar const * msg;
210
+ ulong msg_sz;
211
+ uchar pub[32];
212
+ uchar sig[64];
213
+ uint tc_id;
214
+ int ok;
215
+ };
216
+
217
+ typedef struct fd_ed25519_verify_cctv fd_ed25519_verify_cctv_t;
218
+
219
+ static fd_ed25519_verify_cctv_t const ed25519_verify_cctvs[] = {"""
220
+ )
221
+
222
+ for test in verify_tests :
223
+ if len (test .sig ) != 64 :
224
+ continue
225
+ print (f" {{ .tc_id = { test .tcId } ," )
226
+ print (f' .comment = "{ test .comment } ",' )
227
+ print (
228
+ r' .msg = (uchar const *)"'
229
+ + "" .join ([r"\x%02x" % (x ) for x in test .msg ])
230
+ + r'",'
231
+ )
232
+ print (f" .msg_sz = { len (test .msg )} UL," )
233
+ print (
234
+ r' .sig = "' + "" .join ([r"\x%02x" % (x ) for x in test .sig ]) + r'",'
235
+ )
236
+ print (
237
+ r' .pub = "' + "" .join ([r"\x%02x" % (x ) for x in test .pub ]) + r'",'
238
+ )
239
+ print (f" .ok = { 1 if test .ok else 0 } }}," )
240
+
241
+ print (r" {0}" )
242
+ print (r"};" )
243
+
98
244
def main ():
99
245
with open ("src/ballet/ed25519/test_ed25519_wycheproof.c" , "w" ) as out :
100
246
with redirect_stdout (out ):
101
247
_gen_ed25519 ()
102
248
249
+ with open ("src/ballet/ed25519/test_x25519_wycheproof.c" , "w" ) as out :
250
+ with redirect_stdout (out ):
251
+ _gen_x25519 ()
252
+
253
+ with open ("src/ballet/ed25519/test_ed25519_cctv.c" , "w" ) as out :
254
+ with redirect_stdout (out ):
255
+ _gen_cctv_ed25519 ()
103
256
104
257
if __name__ == "__main__" :
105
258
root = Path (__file__ ).parents [2 ]
0 commit comments