-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathutils.py
More file actions
178 lines (147 loc) · 5.4 KB
/
utils.py
File metadata and controls
178 lines (147 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import base64
import codecs
import math
import struct
from random import SystemRandom
class utils:
prime = 0
def __init__(self, prime=115792089237316195423570985008687907853269984665640564039457584007913129639747):
self.prime = prime
def random(self):
return SystemRandom().randrange(self.prime)
def split_ints(self, secret):
result = []
working = None
byte_object = None
try:
byte_object = bytes(secret, "utf8")
except:
byte_object = bytes(secret)
text = codecs.encode(byte_object, 'hex_codec').decode('utf8') + "00"*(32 - (len(byte_object) % 32))
for i in range(0, int(len(text)/64)):
result.append(int(text[i*64:(i+1)*64], 16))
return result
def merge_ints(self, secrets):
result = ""
for secret in secrets:
hex_data = hex(secret)[2:].replace("L", "")
result += "0"*(64 - (len(hex_data))) + hex_data
byte_object = None
try:
byte_object = bytes(result, "utf8")
return codecs.decode(byte_object, 'hex_codec').decode('utf8').rstrip("\00\x00")
except:
byte_object = bytes(result)
return codecs.decode(byte_object, 'hex_codec').rstrip("\00\x00")
pass
def evaluate_polynomial(self, coefficients, value):
result = 0
for coefficient in reversed(coefficients):
result = result * value + coefficient
result = result % self.prime
return result
def to_base64(self, number):
tmp = hex(number)[2:].replace("L", "")
tmp = "0"*(64 - len(tmp)) + tmp
try:
tmp = bytes(tmp, "utf8")
except:
tmp = bytes(tmp)
result = str(base64.urlsafe_b64encode(b'\00'*(64 - len(tmp)) + codecs.decode(tmp, 'hex_codec')).decode('utf8'))
if len(result) != 44:
print("error: result, tmp, number")
print(result)
print(len(result))
print(tmp)
print(len(tmp))
print(number)
print(hex(number))
print(hex(codecs.decode(tmp, 'hex_codec')))
return result
def from_base64(self, number):
byte_number = number
try:
byte_number = bytes(byte_number, "utf8")
except:
byte_number = bytes(byte_number)
tmp = base64.urlsafe_b64decode(byte_number)
try:
tmp = bytes(tmp, "utf8")
except:
tmp = bytes(tmp)
return int(codecs.encode(tmp, 'hex_codec'), 16)
def gcd(self, a, b):
if b == 0:
return [a, 1, 0]
else:
n = int(math.floor(a*1.0/b))
c = a % b
r = self.gcd(b, c)
return [r[0], r[2], r[1] - r[2]*n]
def mod_inverse(self, number):
remainder = (self.gcd(self.prime, number % self.prime))[2]
if number < 0:
remainder *= -1
return (self.prime + remainder) % self.prime
def shares_to_x_y(self,shares):
x = []
y = []
# must be: len(shares[0])//88 == len(shares[0])/88
for i in range(len(shares[0])//88):
part_x = []
part_y = []
for share in shares:
part_x.append(self.from_base64(share[88*i+0:88*i+44]))
part_y.append(self.from_base64(share[88*i+44:88*i+88]))
x.append(tuple(part_x))
y.append(tuple(part_y))
return x,y
# extended_gcd, divmod, lagrange_interpolate are copied from https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing
def extended_gcd(self, a, b):
"""
Division in integers modulus p means finding the inverse of the
denominator modulo p and then multiplying the numerator by this
inverse (Note: inverse of A is B such that A*B % p == 1) this can
be computed via extended Euclidean algorithm
http://en.wikipedia.org/wiki/Modular_multiplicative_inverse#Computation
"""
x = 0
last_x = 1
y = 1
last_y = 0
while b != 0:
quot = a // b
a, b = b, a % b
x, last_x = last_x - quot * x, x
y, last_y = last_y - quot * y, y
return last_x, last_y
def divmod(self, num, den, p):
"""Compute num / den modulo prime p
To explain what this means, the return value will be such that
the following is true: den * divmod(num, den, p) % p == num
"""
inv, _ = self.extended_gcd(den, p)
return num * inv
def lagrange_interpolate(self, x, x_s, y_s, p):
"""
Find the y-value for the given x, given n (x, y) points;
k points will define a polynomial of up to kth order.
"""
k = len(x_s)
assert k == len(set(x_s)), "points must be distinct"
def PI(vals): # upper-case PI -- product of inputs
accum = 1
for v in vals:
accum *= v
return accum
nums = [] # avoid inexact division
dens = []
for i in range(k):
others = list(x_s)
cur = others.pop(i)
nums.append(PI(x - o for o in others))
dens.append(PI(cur - o for o in others))
den = PI(dens)
num = sum([self.divmod(nums[i] * den * y_s[i] % p, dens[i], p)
for i in range(k)])
return (self.divmod(num, den, p) + p) % p