Guest User

Untitled

a guest
Aug 2nd, 2023
407
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.01 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. import random
  3. import time
  4.  
  5. def rabin_miller(n, certainty=128):
  6.     """Determine if a positive integer is (probably) a prime.
  7.  
  8.    Positional argument:
  9.  
  10.        n   --      The positive integer to check for primality.
  11.  
  12.    Keyword argument:
  13.  
  14.        certainty   --  How sure you want to be than n really is a prime. See
  15.                        below for details.
  16.  
  17.    Returns:
  18.  
  19.        True        --  n is probably prime. The probability that n is not
  20.                        prime is <= 1/2**certainty.
  21.        False       --  n is *definitely* not prime.
  22.    """
  23.     rand = random.SystemRandom()
  24.     def test_once(d,r,n):
  25.         a = rand.randint(2, n-2)
  26.         x = pow(a, d, n)
  27.         if x == 1 or x == n-1: return True
  28.         for i in range(1,r):
  29.             x = (x*x) % n
  30.             if x == n-1: return True
  31.         return False
  32.        
  33.     # Take care of special cases
  34.     if n == 2 or n == 3: return True
  35.     if n == 1 or n % 2 == 0: return False
  36.  
  37.     # Find r, d such that n = 2**r * d + 1, with d odd
  38.     d = n - 1
  39.     r = 0
  40.     while d % 2 == 0:
  41.         d = d // 2
  42.         r += 1
  43.     for t in range(certainty//2+1):
  44.         if test_once(d,r,n) == False:
  45.             return False
  46.     return True
  47.  
  48. def find_prime(start=0, bits=0, linear=True):
  49.     """Find a randomly chosen prime of a given number of bits, or find the
  50.    first prime >= a given number.
  51.  
  52.    Keyword arguments:
  53.  
  54.        bits    --  Number of bits if you want a random prime.
  55.  
  56.        start   --  Starting search position if you want a non-random prime.
  57.  
  58.        linear  --  Controls search for random primes. See below.
  59.  
  60.        Note: you should specify exactly one of "bits" and "start".
  61.  
  62.    Returns:
  63.  
  64.        prime   --  A prime number
  65.  
  66.    When searching for a random prime, "linear" specifies what happens if
  67.    the random number it picks is not prime. If linear is True, it will add
  68.    2 and check that number. If linear is False, it will pick another random
  69.    number to check. When linear is True, if adding 2 would take it past
  70.    2**bits, it will wrap to 2**(bits-1)+1.
  71.    """
  72.     rand = random.SystemRandom()
  73.     if bits != 0 and start == 0:
  74.         base = 2**(bits-1)
  75.         wrap = 2*base
  76.         p = rand.randint(base, wrap-1) | 1
  77.     elif bits == 0 and start != 0:
  78.         if start <= 2:
  79.             return 2
  80.         p = start | 1
  81.         linear = True
  82.         base = start ^ 1
  83.         wrap = 2 * p
  84.     else:
  85.         print("Error: find_prime must be given exactly one of bits and start")
  86.         return 0
  87.     while not rabin_miller(p):
  88.         if linear:
  89.             p += 2
  90.             if p >= wrap:
  91.                 p = base + 1
  92.         else:
  93.             p = rand.randint(base, wrap-1) | 1
  94.     return p
  95.  
  96. def poly_at(x, poly, m):
  97.     y = 0
  98.     f = 1
  99.     for c in poly:
  100.         y += c * f
  101.         y = y % m
  102.         f = (f * x) % m
  103.     return y
  104.  
  105. def row_multiply(r, a, m):
  106.     """multiply row `r` by ``a` mod `m`"""
  107.     for i in range(len(r)):
  108.         r[i] = (r[i] * a) % m
  109.  
  110. def row_multiply_add(r, r2, a, m):
  111.     for i in range(len(r)):
  112.         r[i] = (r[i] + r2[i] * a) % m
  113.  
  114. def zero_column(eqs, c, r, m):
  115.     row_multiply(eqs[r], pow(eqs[r][c], -1, m), m)
  116.     for j in range(len(eqs)):
  117.         if j != r:
  118.             a = (m - eqs[j][c]) % m
  119.             row_multiply_add(eqs[j], eqs[r], a, m)
  120.  
  121. def solve(eqs, m):
  122.     for d in range(len(eqs)):
  123.         if eqs[d][d] == 0:
  124.             for j in range(d+1,len(eqs)):
  125.                 if eqs[j][d] != 0:
  126.                     eqs[d], eqs[j] = eqs[j], eqs[d]
  127.                     print("swap rows",d,"and",j)
  128.                     break
  129.         zero_column(eqs, d, d, m)
  130.  
  131. def recover_secret(shares, p):
  132.     num_shares = len(shares)
  133.     equations = []
  134.     for r in range(num_shares):
  135.         i, share_i = shares[r]
  136.         g = 1
  137.         row = [1]
  138.         for t in range(1, num_shares):
  139.             g = (g * i) % p
  140.             row.append(g)
  141.         row.append(share_i)
  142.         equations.append(row)
  143.     solve(equations, p)
  144.     return [r[-1] for r in equations]
  145.  
  146. def make_sss(s, k, p=0):
  147.     """make a secret sharing scheme to share secret `s` with `k` shares
  148.    required to reconstruct the secret"""
  149.     rand = random.SystemRandom()
  150.     if p == 0:
  151.         bits = 2
  152.         base = 2
  153.         while base <= s:
  154.             base *= 2
  155.             bits += 1
  156.         p = find_prime(bits=bits, linear=False)
  157.     else:
  158.         if s >= p:
  159.             print("secret is too large for prime")
  160.             return (0, [])
  161.     poly = [s]
  162.     for i in range(k-1):
  163.         poly.append(rand.randint(1, p-1))
  164.     return (p, poly)
  165.  
  166. def make_share(sss, i):
  167.     return poly_at(i, sss[1], sss[0])
  168.  
  169. if __name__ == "__main__":
  170.     rand = random.SystemRandom()
  171.     k = 3
  172.     bits = 128
  173.     sss = make_sss(rand.randint(1, 2**bits-1), k)
  174.     print("prime", sss[0])
  175.     print(sss[1])
  176.     shares = [[i**2+1, make_share(sss, i**2+1)] for i in range(k)]
  177.     poly = recover_secret(shares, sss[0])
  178.     print(poly)
  179.     print(shares)
  180.  
Advertisement
Add Comment
Please, Sign In to add comment