def __init__(self, P, Q, s=1, strict=False): ''' if strict == True: use Carmichael Number else: use Euler Number ''' N = P * Q # Lam = lcm(P-1, Q-1) G = field(N**s, "G") # n ** s == n if s = 1 # multiplicative group MG = field(N**(s + 1), "N^{s+1}") # n ** (s +1 ) == n2 in pailer case H = field(N, "H") # https://crypto.stackexchange.com/questions/29591/lcm-versus-phi-in-rsa if strict: LG = field(rsa_lambda(P, Q), "PhiGroup") else: LG = field(rsa_phi(P, Q), "PhiGroup") j = generate_prime(length(P)) assert gcd(j, N) == 1 x = randfield(H) g = MG((MG(1 + N)**j) * x) d = crt(a_list=[0, 1], n_list=[LG.P, G.P]) assert d % G.P == 1 assert d % LG.P == 0 self.s = s self.privkey = d self.N = N self.G = g self.pubkey = (N, g)
def setup(self, secret, k, n, poly_params = []): if not poly_params: poly_params = [randfield(self.F) for _ in range(k - 1)] self.poly_proofs = [self.G ** p for p in [secret] + poly_params] return super().setup(secret, k, n, poly_params)
def join(self, x=None): assert x != 0 if not x: x = randfield(self.F) if not hasattr(self, 'f'): raise Exception("Needs to encrypt first") return (self.F(x), self.f(x))
def encrypt(cls, m, pub): g, h = pub y = randfield(field(g.N)).value m_ = map_to_curve(m) s = h ** y c1 = g ** y c2 = s * m_ return (c1, c2)
def commit(self, m, ak): pk, vk, h = self.key com = PedersonCommitment(H, G, pk, ak) # (𝑐,𝑑)=𝐻𝑆𝑐𝑜𝑚𝑚𝑖𝑡𝑝𝑘(𝑎𝑘) c, d = com.C, com.D # α=ℎ(𝑐) alpha = CF(to_sha256int(gen_address(c))) # Now we simulate a proof of knowledge of a signature on 𝛼 with challenge 𝑚 S = PedersonCommitment(H, G, vk, alpha) r1, r2 = randfield(vk.functor), randfield(vk.functor) a = S.commit(r1, r2) z = S.challenge(m) self.S = S # Finally, we compute 𝑚𝑎𝑐=𝑀𝐴𝐶𝑎𝑘(𝑎). mac = hmac.new(str(ak.value).encode(), encode_pubkey(a).encode()).hexdigest() self.c = (c, a, mac) self.d = (m, d , z)
def encrypt(cls, m, pub, s=1, r=None): N, G = pub if hasattr(m, "value"): m = m.value if not r: r = randfield(G.functor) else: r = G.functor(r) return G**m * r**(N**s)
def test_ssss(): F = field(P) s = SSSS(F) k = random.randint(1, 100) n = k * 3 secret = randfield(F) s.setup(secret, k, n) assert s.decrypt([s.join() for _ in range(k - 1)]) != secret assert s.decrypt([s.join() for _ in range(k + 1)]) == secret assert s.decrypt([s.join() for _ in range(k + 2)]) == secret
def setup(self, secret, k, n, poly_params=[]): ''' k: threshold ''' self.k = k self.n = n if not poly_params: poly_params = [randfield(self.F) for _ in range(k - 1)] self.f = lambda x: self.F(secret) + reduce( add, [poly_params[i] * (x**(i + 1)) for i in range(k - 1)]) return self
def __init__(self, P, Q): assert gcd(P * Q, (P - 1) * (Q - 1)) == 1 N = P * Q Lam = lcm(P - 1, Q - 1) F = field(N) DF = field(N**2) G = randfield(DF) M = ~F(L(pow(G, Lam).value, N)) self.N = N self.G = G self.privkey = Lam self.pubkey = (self.N, self.G)
def additive_share(secret, F, n): shares = [randfield(F) for _ in range(n - 1)] shares += [(F(secret) - reduce(add, shares))] return shares
def keygen(F): pk = randfield(F) vk = F(to_sha256int(str(pk.value))) h = gen_address return (pk, vk, h)