9
9
decode_matrix , \
10
10
decode_matrices , \
11
11
encode_matrices , \
12
- partial_encode_matrices , \
13
- partial_decode_matrices , \
14
- upper , \
15
- bitsliced_upper , \
16
- bitsliced_matrices_add , \
17
- bitsliced_matrices_matrix_mul , \
18
- bitsliced_matrix_matrices_mul
12
+ upper
19
13
from sagelib .aes256_ctr_drbg \
20
14
import AES256_CTR_DRBG
21
15
from sagelib .aes128_ctr \
@@ -33,23 +27,6 @@ F16 = GF(16, names=('x',))
33
27
assert x ** 4 + x + 1 == 0
34
28
R = F16 ['z' ]
35
29
(z ,) = R ._first_ngens (1 )
36
- # import itertools
37
- # F.<x> = GF(16)
38
- # R.<y> = F[]
39
- # m = 72
40
- # for c0 in F:
41
- # if c0 in ZZ:
42
- # continue
43
- # f0 = y^m + c0
44
- # for w in range(1,3):
45
- # for js in itertools.combinations(list(range(1,m)), w):
46
- # f = f0 + sum(y^j for j in js)
47
- # if f.is_irreducible():
48
- # print(f)
49
-
50
- assert (z ** 64 + x ** 3 * z ** 3 + x * z ** 2 + x ** 3 ).is_irreducible ()
51
- assert (z ** 96 + x * z ** 3 + x * z + x ).is_irreducible ()
52
- assert (z ** 128 + x * z ** 4 + x ** 2 * z ** 3 + x ** 3 * z + x ** 2 ).is_irreducible ()
53
30
54
31
# The parameters for the MAYO variants. They are:
55
32
# q (the size of the finite field F_q), m (the number of multivariate quadratic polynomials in the public key),
@@ -58,21 +35,21 @@ assert (z**128 + x*z**4 + x**2*z**3 + x**3*z + x**2).is_irreducible()
58
35
DEFAULT_PARAMETERS = {
59
36
"mayo_1" : {
60
37
"name" : "mayo1" ,
61
- "n" : 66 ,
62
- "m" : 64 ,
38
+ "n" : 86 ,
39
+ "m" : 78 ,
63
40
"o" : 8 ,
64
- "k" : 9 ,
41
+ "k" : 10 ,
65
42
"q" : 16 ,
66
43
"sk_salt_bytes" : 24 ,
67
44
"pk_bytes" : 16 ,
68
45
"digest_bytes" : 32 ,
69
- "f" : z ** 64 + x ** 3 * z ** 3 + x * z ** 2 + x ** 3
46
+ "f" : z ** 78 + z ** 2 + z + x ** 3
70
47
},
71
48
"mayo_2" : {
72
49
"name" : "mayo2" ,
73
- "n" : 78 ,
50
+ "n" : 81 ,
74
51
"m" : 64 ,
75
- "o" : 18 ,
52
+ "o" : 17 ,
76
53
"k" : 4 ,
77
54
"q" : 16 ,
78
55
"sk_salt_bytes" : 24 ,
@@ -82,27 +59,27 @@ DEFAULT_PARAMETERS = {
82
59
},
83
60
"mayo_3" : {
84
61
"name" : "mayo3" ,
85
- "n" : 99 ,
86
- "m" : 96 ,
62
+ "n" : 118 ,
63
+ "m" : 108 ,
87
64
"o" : 10 ,
88
65
"k" : 11 ,
89
66
"q" : 16 ,
90
67
"sk_salt_bytes" : 32 ,
91
68
"pk_bytes" : 16 ,
92
69
"digest_bytes" : 48 ,
93
- "f" : z ** 96 + x * z ** 3 + x * z + x
70
+ "f" : z ** 108 + ( x ** 2 + x + 1 ) * z ** 3 + z ** 2 + x ** 3
94
71
},
95
72
"mayo_5" : {
96
73
"name" : "mayo5" ,
97
- "n" : 133 ,
98
- "m" : 128 ,
74
+ "n" : 154 ,
75
+ "m" : 142 ,
99
76
"o" : 12 ,
100
77
"k" : 12 ,
101
78
"q" : 16 ,
102
79
"sk_salt_bytes" : 40 ,
103
80
"pk_bytes" : 16 ,
104
81
"digest_bytes" : 64 ,
105
- "f" : z ** 128 + x * z ** 4 + x ** 2 * z ** 3 + x ** 3 * z + x ** 2
82
+ "f" : z ** 142 + z ** 3 + x ** 3 * z ** 2 + x ** 2
106
83
},
107
84
}
108
85
@@ -127,8 +104,7 @@ class Mayo:
127
104
self .O_bytes = math .ceil ((self .n - self .o )* self .o * self .q_bytes )
128
105
self .v_bytes = math .ceil ((self .n - self .o ) * self .q_bytes )
129
106
self .r_bytes = math .ceil (self .k * self .o * self .q_bytes )
130
- self .P1_bytes = math .ceil (
131
- self .m * math .comb ((self .n - self .o + 1 ), 2 ) * self .q_bytes )
107
+ self .P1_bytes = math .ceil (self .m * math .comb ((self .n - self .o + 1 ), 2 ) * self .q_bytes )
132
108
self .P2_bytes = math .ceil (self .m * (self .n - self .o )* self .o * self .q_bytes )
133
109
self .P3_bytes = math .ceil (self .m * math .comb ((self .o + 1 ), 2 ) * self .q_bytes )
134
110
@@ -194,6 +170,7 @@ class Mayo:
194
170
self .o , self .n - self .o , triangular = True ) # {P_i^(1)}_(i in [m]) <- Decode_(P(1))(p[0 : P1_bytes])
195
171
p2 = decode_matrices (p [self .P1_bytes :self .P1_bytes + self .P2_bytes ],
196
172
self .m , self .n - self .o , self .o , triangular = False ) # {P_i^(2)}_(i in [m]) <- Decode_(P(2))(p[P1_bytes : P1_bytes + P2_bytes])
173
+
197
174
# for i from 0 to m − 1 do
198
175
# P(3) <- Upper(−O^(T)P_i^(1) O − O^(T)P_i^((2))
199
176
p3 = [matrix (F16 , self .o , self .o ) for _ in range (self .m )]
@@ -204,40 +181,6 @@ class Mayo:
204
181
csk = seed_sk # csk <- seedsk
205
182
return csk , cpk
206
183
207
- def compact_key_gen_bitsliced (self ):
208
- """
209
- outputs a pair (csk, cpk) in B^{csk_bytes} x B^{cpk_bytes}, where csk and cpk
210
- are compact representations of a secret key and public key
211
- """
212
- seed_sk = self .random_bytes (self .sk_seed_bytes )
213
-
214
- s = shake_256 (seed_sk ).digest (int (self .pk_seed_bytes + self .O_bytes ))
215
- seed_pk = s [:self .pk_seed_bytes ]
216
-
217
- o = decode_matrix (s [self .pk_seed_bytes :self .pk_seed_bytes +
218
- self .O_bytes ], self .n - self .o , self .o )
219
-
220
- ctr = AES128_CTR (seed_pk , self .P1_bytes + self .P2_bytes )
221
- p = ctr .aes_ctr_gen ()
222
-
223
- p1 = partial_decode_matrices (p [:self .P1_bytes ], self .m , self .n -
224
- self .o , self .n - self .o , triangular = True )
225
-
226
- p2 = partial_decode_matrices (p [self .P1_bytes :self .P1_bytes + self .P2_bytes ],
227
- self .m , self .n - self .o , self .o , triangular = False )
228
-
229
- p3 = [ [ None for _ in range (self .o )] for _ in range (self .o ) ]
230
-
231
- # compute p1o + p2
232
- p1o_p2 = bitsliced_matrices_add (bitsliced_matrices_matrix_mul (p1 ,o ),p2 )
233
- # compute p3
234
- p3 = bitsliced_matrix_matrices_mul (o .transpose (), p1o_p2 )
235
- p3 = bitsliced_upper (p3 )
236
-
237
- cpk = seed_pk + partial_encode_matrices (p3 , self .m , self .o , self .o , triangular = True )
238
- csk = seed_sk
239
- return csk , cpk
240
-
241
184
def expand_sk (self , csk ):
242
185
"""
243
186
takes as input csk, the compact representation of a secret key, and outputs sk in B^{sk_bytes},
@@ -270,43 +213,6 @@ class Mayo:
270
213
esk = seed_sk + o_bytestring + p [0 :self .P1_bytes ] + encode_matrices (l , self .m , self .n - self .o , self .o , triangular = False )
271
214
return esk
272
215
273
- def expand_sk_bitsliced (self , csk ):
274
- """
275
- takes as input csk, the compact representation of a secret key, and outputs sk in B^{sk_bytes},
276
- an expanded representation of the secret key
277
- """
278
- assert len (csk ) == self .csk_bytes
279
-
280
- seed_sk = csk
281
- s = shake_256 (seed_sk ).digest (int (self .pk_seed_bytes + self .O_bytes ))
282
- seed_pk = s [:self .pk_seed_bytes ]
283
-
284
- o_bytestring = s [self .pk_seed_bytes :self .pk_seed_bytes + self .O_bytes ]
285
- o = decode_matrix (o_bytestring , self .n - self .o , self .o )
286
-
287
- ctr = AES128_CTR (seed_pk , self .P1_bytes + self .P2_bytes )
288
- p = ctr .aes_ctr_gen ()
289
-
290
- p1 = partial_decode_matrices (p [:self .P1_bytes ], self .m , self .n -
291
- self .o , self .n - self .o , triangular = True )
292
-
293
- p2 = partial_decode_matrices (p [self .P1_bytes :self .P1_bytes + self .P2_bytes ],
294
- self .m , self .n - self .o , self .o , triangular = False )
295
-
296
- # compute (p1 + p1^t)
297
- p1_p1t = p1 .copy ()
298
- for i in range (self .n - self .o ):
299
- p1_p1t [i ][i ] = (0 ,0 ,0 ,0 )
300
- for j in range (i + 1 ,self .n - self .o ):
301
- p1_p1t [j ][i ] = p1_p1t [i ][j ]
302
-
303
- # compute (p1 + p1^t)*o + p2
304
- l = bitsliced_matrices_add (bitsliced_matrices_matrix_mul (p1_p1t , o ), p2 )
305
-
306
- esk = seed_sk + o_bytestring + p [:self .P1_bytes ] + partial_encode_matrices (l , self .m , self .n - self .o , self .o , triangular = False )
307
-
308
- return esk
309
-
310
216
def expand_pk (self , cpk ):
311
217
"""
312
218
takes as input cpk and outputs pk in B^{pk_bytes}
0 commit comments