defproduct(vals, p): return reduce(lambda x, y: x * y % p, vals)
deflagrange_interpolate(x, x_s, y_s, p): n = len(x_s) assert n == len(set(x_s)) # x_s must be distinct num = [] den = [] for i in range(n): others = x_s[:i] + x_s[i+1:] num.append(product((x - o for o in others), p)) den.append(product((x_s[i] - o for o in others), p)) dens = product(den, p) res = 0 for i in range(n): tmp1 = ((num[i] * dens % p) * y_s[i]) % p tmp2 = tmp1 * gmpy2.invert(den[i], p) % p res = (res + tmp2) % p res = res * gmpy2.invert(dens, p) % p return res
defshamir_sharing_encode(s, k, n, p): a = [getRandomInteger(Nbits) for _ in range(k-1)] res = [] for _ in range(n): x = getRandomInteger(Nbits) fx = s for i in range(k-1): fx = (fx + a[i] * pow(x, i+1, p)) % p res.append((x, fx)) return res
Nbits = 1024 secret = bytes_to_long('it_is_the_top_secret') p = getPrime(Nbits) k = 513 n = 513
shares = shamir_sharing_encode(secret, k, n, p)
s = shamir_sharing_decode(shares, p) print long_to_bytes(s) # 2s
当然解密算法也可以用 sage,更方便:
1 2 3 4 5 6 7 8 9 10
P = PolynomialRing(GF(p), 'x') ret = P(0) for x, y in shares: r = P(1) * y for xx, yy in shares: if x != xx: r = r * P((0 - xx) / (x - xx)) ret = ret + r print ret # 19s
也可以用 sage 算出所有的系数,但相应的解密时间也会很长:
1 2 3 4 5 6 7 8 9 10
P = PolynomialRing(GF(p), 'x') ret = P(0) for x, y in shares: r = P(1) * y for xx, yy in shares: if x != xx: r = r * P('(x - %d) / (%d - %d)' % (xx, x, xx)) ret = ret + r print ret[0] # 154s
array_1 = [] for i in range(fx_num): for j in range(fx_num): array_1.append(pow(x[i], j, p)) delta = matrix(GF(p), fx_num, fx_num, array_1).determinant()
array_2 = [_ for _ in array_1] for i in range(fx_num): array_2[i*fx_num] = y[i] delta_0 = matrix(GF(p), fx_num, fx_num, array_2).determinant() % p
delta_inverse = inverse_mod(int(delta), p) res = delta_inverse * delta_0 % p print res # 1200s
delta = 1 for i in range(1, fx_num): for j in range(0, i): t = x[i] - x[j] delta = (delta * t) % p
delta_0 = 0 for i in range(fx_num): tmp_x = [_ for _ in x] tmp_x.pop(i) yuzishi = -y[i] if (i+1+1) % 2else y[i] for j in range(fx_num-1): yuzishi = (yuzishi * tmp_x[j]) % p for j in range(1, fx_num-1): for k in range(0, j): t = tmp_x[j] - tmp_x[k] yuzishi = (yuzishi * t) % p delta_0 = (delta_0 + yuzishi) % p
delta_inverse = gmpy2.invert(delta, p) res = delta_inverse * delta_0 % p print res # 224s
Problem
如果在加密 2 段明文 s1、s2 过程中,使用相同的随机数 a 以及大素数 p,还能得到同一个 x 对应的两个 f(x),如果知道一个明文 s1 的情况下,可以算出另一个明文。