def addingPoints(P, Q, p, a): if P == 0 and Q == 0: return 0 if P == 0 or Q == 0: if P == 0: return Q if Q == 0: return P if P == Q: return doublingPoint(P, p, a) xP, yP = P xQ, yQ = Q if xP == xQ and yQ == (p - yP): return 0 numerator = yP - yQ denominator = xP - xQ # gcd = extendedGCD(numerator, denominator) # numerator /= gcd # denominator /= gcd m = (numerator * modularInverse(denominator, p)) % p xR = (m**2 - xP - xQ) % p yR = (m * (xP - xR) - yP) % p return (xR, yR)
def doublingPoint(P, p, a): if P == 0: return 0 # print(f'P = {P}') xP, yP = P m = ((3 * xP**2 + a) * modularInverse(2 * yP, p)) % p xR = (m**2 - 2 * xP) % p yR = (m * (xP - xR) - yP) % p return (xR, yR)
def generateSignature(p, a, b, G, n, d, message): k = random.randint(1, n - 1) kG = doubleAndAdd(k, G, p, a) r = kG[0] % n if r == 0: generateSignature(p, a, b, G, n, d, message) return None hx = digitizeString(message) s = (modularInverse(k, n) * (hx + d * r)) % n if s == 0: generateSignature(p, a, b, G, n, d, message) return None print(f'k = {k}') print(f'kG = {kG}') print(f'r = x1 mod n = {kG[0]} mod {n}') print(f'hx = so hoa "{message}" = {hx}') print( f's = (k^(-1) * (hx + dr)) mod n = ({k}^(-1) * ({hx} + {d}*{r})) mod {n}' ) return (r, s)
def testSignature(key, signature, n, message): public_key, d = key Ep, G, _, Q = public_key p, a, b = Ep r, s = signature if r not in range(1, n): print('r = {r} not in [1, n-1={n-1}]') return False print(f'r = {r} in [1, n-1={n-1}]') if s not in range(1, n): print(f's = {s} not in [1, n-1={n-1}]') return False print(f's = {s} in [1, n-1={n-1}]') w = modularInverse(s, n) hx = digitizeString(message) u1 = hx * w % n u2 = r * w % n x0, y0 = addingPoints(doubleAndAdd(u1, G, p, a), doubleAndAdd(u2, Q, p, a), p, a) v = x0 % n print(f'w = s^(-1) mod n = {s}^(-1) mod {n} = {w}') print(f'hx = so hoa "{message}" = {hx}') print(f'u1 = hx*w mod n = {hx}*{w} mod {n} = {u1}') print(f'u2 = r*w mod n = {r}*{w} mod {n} = {u2}') print(f'(x0, y0) = u1G + u2Q = {u1}{G} + {u2}{Q} = ({x0}, {y0})') print(f'v = x0 mod n = {x0} mod {n} = {v}') if v != r: print(f'v={v} not equal r={r} => False') return False print(f'v = r = {v} => True') return True
def rsaSolver(pq_digits, e_digits, text): p = generatePrime(pq_digits)[0] q = generatePrime(pq_digits)[0] n = p * q r = (p - 1) * (q - 1) e = generatePrime(e_digits)[0] d = modularInverse(e, r) x = digitizeString(text) c = pow(x, e, n) m = pow(c, d, n) if x != m: rsaSolver(pq_digits, e_digits, text) return None print('\n============================================================') print(f'p = {p:d}\nq = {q:d}\n') print('n = p * q') print(f'= {p:d} * {q:d}') print(f'= {n:d}') print('r = (p - 1) * (q - 1)') print(f'= {p-1:d} * {q-1:d}') print(f'= {r:d}\n') print(f'e = {e:d}') print('d = e^(-1) mod r') print(f'= {d:d}\n') print(f'x = {x:d}\n') print('Encrypt:\n') print('c = x^e mod n') print(f'= {c:d}\n') print('Decrypt:\n') print('m = c^d mod n') print(f'= {m:d}\n= x') print('============================================================\n')
def Chaum_vanAntverpenSignatureSolver(p_range, alpha_range, message): p_left, p_right = p_range alpha_left, alpha_right = alpha_range p = generateSophieGermainPrime(p_left, p_right)[0] q = (p - 1) // 2 primitive = getPrimitiveRootList(p)[1] primitive = random.choice( list(filter(lambda x: alpha_left < x and x < alpha_right, primitive))) alpha = primitive**2 % p a = random.randint(1, q - 1) beta = pow(alpha, a, p) x = digitizeString(message) y = signature = pow(x, a, p) e_range = list(range((q - 1) // 2, q)) e1 = random.choice(e_range) e_range.remove(e1) e2 = random.choice(e_range) e_range.remove(e2) c = pow(y, e1, p) * pow(beta, e2, p) % p d = pow(c, modularInverse(a, q), p) verify = pow(x, e1, p) * pow(alpha, e2, p) % p if verify != d: Chaum_vanAntverpenSignatureSolver(p_range, alpha_range, message) return None # ============================================================================= # f1 = random.choice(e_range) # e_range.remove(f1) # f2 = random.choice(e_range) # # C = pow(y, f1, p) * pow(beta, f2, p) % p # # D = pow(C, modularInverse(a, q), p) # # temp = pow(x, f1, p) * pow(alpha, f2, p) % p # verify2 = (D != temp) # ============================================================================= print('================================================================') print('a) Confirmation protocol:') print('Generate Sophie Germain prime p = 2q + 1:') print(f'p = {p} = 2*{q} + 1; {p} is prime and {q} is prime') print( f'Since {primitive} is a primitive root of p={p}, hence {primitive}^2 mod {p} = {alpha} is a generator of group of quadratic residues modulo p={p} and of order of q={q}' ) print( f'Generate a in range [1, q-1={q-1}]. Suppose a={a}, then beta = alpha^a mod p = {alpha}^{a} mod {p} = {beta}' ) print() print(f'Public key: (p, alpha, beta) = ({p}, {alpha}, {beta})') print(f'Private key: a = {a}') print() print(f'message = {message} => x = digitize("{message}") mod {p} = {x}') print( f'Bob sign the message with the signature y = x^a mod p = {x}^{a} mod {p} = {y} and send the pairs (x, signature) = ({x}, {y}) to Alice' ) print() print( f'When receiving the message x, Alice wants to verify the signature y. Suppose Alice generated e1={e1} and e2={e2} in range [1, q-1={q-1}], then she will compute:' ) print( f'c = y^e1 * beta^e2 mod p = {y}^{e1} * {beta}^{e2} mod {p} = {c} and send it to Bob' ) print() print('Bob will then compute:') print( f'd = c^(a^(-1) mod q) mod p = {c}^({a}^(-1) mod {q}) mod {p} = {d} and send it back to Alice' ) print() print('Alice then check Bob\'s response by verifying that:') print( f'x^e1 * alpha^e2 mod p = {x}^{e1} * {alpha}^{e2} mod {p} = {verify} = d' ) print( f'Hence, Alice accepted that the signature y={y} is valid for the message x={x}' ) # ============================================================================= # print() # print('b) Disavowal protocol:') # print('In case when d =/= x^e1 * alpha^e2 mod p, Alice has to consider whether y is a forgery or Bob denies his signature. To evaluate this, Alice continues the verification using the following disavowal protocol:') # ============================================================================= print('================================================================\n')