@@ -77,7 +77,8 @@ def _div_gf2(a, b):
77
77
class _Element (object ):
78
78
"""Element of GF(2^128) field"""
79
79
80
- # The irreducible polynomial defining this field is 1+x+x^2+x^7+x^128
80
+ # The irreducible polynomial defining
81
+ # this field is 1 + x + x^2 + x^7 + x^128
81
82
irr_poly = 1 + 2 + 4 + 128 + 2 ** 128
82
83
83
84
def __init__ (self , encoded_value ):
@@ -178,43 +179,53 @@ def split(k, n, secret, ssss=False):
178
179
179
180
Args:
180
181
k (integer):
181
- The sufficient number of shares to reconstruct the secret (``k < n``) .
182
+ The number of shares needed to reconstruct the secret.
182
183
n (integer):
183
- The number of shares that this method will create .
184
+ The number of shares to create (at least ``k``) .
184
185
secret (byte string):
185
- A byte string of 16 bytes (e.g. the AES 128 key).
186
+ A byte string of 16 bytes (e.g. an AES 128 key).
186
187
ssss (bool):
187
- If ``True``, the shares can be used with the ``ssss`` utility.
188
+ If ``True``, the shares can be used with the ``ssss`` utility
189
+ (without using the "diffusion layer").
188
190
Default: ``False``.
189
191
190
192
Return (tuples):
191
- ``n`` tuples. A tuple is meant for each participant and it contains two items:
193
+ ``n`` tuples, one per participant.
194
+ A tuple contains two items:
192
195
193
196
1. the unique index (an integer)
194
- 2. the share (a byte string, 16 bytes)
197
+ 2. the share (16 bytes)
195
198
"""
196
199
197
200
#
198
201
# We create a polynomial with random coefficients in GF(2^128):
199
202
#
200
- # p(x) = \sum_{i=0 }^{k-1} c_i * x^i
203
+ # p(x) = c_0 + \sum_{i=1 }^{k-1} c_i * x^i
201
204
#
202
- # c_0 is the encoded secret
205
+ # c_0 is the secret.
203
206
#
204
207
205
208
coeffs = [_Element (rng (16 )) for i in range (k - 1 )]
206
209
coeffs .append (_Element (secret ))
207
210
208
- # Each share is y_i = p(x_i) where x_i is the public index
209
- # associated to each of the n users .
211
+ # Each share is y_i = p(x_i) where x_i
212
+ # is the index assigned to the share .
210
213
211
214
def make_share (user , coeffs , ssss ):
212
215
idx = _Element (user )
216
+
217
+ # Horner's method
213
218
share = _Element (0 )
214
219
for coeff in coeffs :
215
220
share = idx * share + coeff
221
+
222
+ # The ssss utility actually uses:
223
+ #
224
+ # p(x) = c_0 + \sum_{i=1}^{k-1} c_i * x^i + x^k
225
+ #
216
226
if ssss :
217
227
share += _Element (user ) ** len (coeffs )
228
+
218
229
return share .encode ()
219
230
220
231
return [(i , make_share (i , coeffs , ssss )) for i in range (1 , n + 1 )]
@@ -225,11 +236,18 @@ def combine(shares, ssss=False):
225
236
226
237
Args:
227
238
shares (tuples):
228
- The *k* tuples, each containin the index (an integer) and
239
+ The *k* tuples, each containing the index (an integer) and
229
240
the share (a byte string, 16 bytes long) that were assigned to
230
241
a participant.
242
+
243
+ .. note::
244
+
245
+ Pass exactly as many share as they are required,
246
+ and no more.
247
+
231
248
ssss (bool):
232
- If ``True``, the shares were produced by the ``ssss`` utility.
249
+ If ``True``, the shares were produced by the ``ssss`` utility
250
+ (without using the "diffusion layer").
233
251
Default: ``False``.
234
252
235
253
Return:
@@ -275,4 +293,5 @@ def combine(shares, ssss=False):
275
293
numerator *= x_m
276
294
denominator *= x_j + x_m
277
295
result += y_j * numerator * denominator .inverse ()
296
+
278
297
return result .encode ()
0 commit comments