Skip to content

Instantly share code, notes, and snippets.

@DennySORA
Created September 15, 2020 12:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save DennySORA/b2c300cbc7de75c0e4c28166241ff07b to your computer and use it in GitHub Desktop.
Save DennySORA/b2c300cbc7de75c0e4c28166241ff07b to your computer and use it in GitHub Desktop.
import random
from typing import Tuple
def get_reciprocal(value: int, mod: int) -> int:
for i in range(1, mod):
if (i * value) % mod == 1:
return i
return -1
def get_gcd(a: int, b: int) -> int:
return a if b == 0 else get_gcd(b, a % b)
def get_q(p: Tuple[int, int], q: Tuple[int, int], a: int, mod: int) -> Tuple[int, int]:
def get_s(p: Tuple[int, int], q: Tuple[int, int], a: int, mod: int) -> int:
negative = 1
if p == q:
numerator = 3 * (p[0] ** 2) + a
denominator = 2 * p[1]
else:
numerator = q[1] - p[1]
denominator = q[0] - p[0]
if numerator < 0 or denominator < 0:
negative = -1
numerator = abs(numerator)
denominator = abs(denominator)
gcd = get_gcd(numerator, denominator)
numerator = numerator // gcd
denominator = denominator // gcd
# Get reciprocal
reciprocal = get_reciprocal(denominator, mod)
return (negative*numerator * reciprocal) % mod
s = get_s(p, q, a, mod)
xr = (s**2-p[0]-q[0]) % mod
yr = (s*(p[0]-xr) - p[1]) % mod
return xr, yr
def get_xg_or_n(g: Tuple[int, int], xg: Tuple[int, int], x: int, a: int, mod: int) -> Tuple[int, int]:
temp = xg
symmetry_y = (-1*g[1]) % mod
n = 0
while x != 1 or x == -1:
n += 1
print(temp, g, x, 7)
temp = get_q(temp, g, a, mod)
if x != -1:
x -= 1
elif g[0] == temp[0] and symmetry_y == temp[1]:
return (n, symmetry_y)
print(8)
return temp
def get_point(a: int, b: int, mod: int, lens: int) -> Tuple[int, int]:
while True:
x = random.randint(10**(lens-1), 10**lens-1)
for _ in range(100):
y = random.randint(10**(lens-1), 10**lens-1)
if (y ** 2 % mod) == ((x**3+x*a+b) % mod):
print(9)
return x, y
def gen_key(g: Tuple[int, int], n: int, a: int, mod: int) -> Tuple[int, Tuple[int, int]]:
print(4)
private_key = random.randint(0, n)
print(5)
public_key = get_xg_or_n(g,g, private_key, a, mod)
print(6)
return private_key, public_key
def gen_g(a: int, b: int, mod: int, lens: int) -> Tuple[Tuple[int, int], int]:
print(1)
g = get_point(a, b, mod, lens)
return g,9999
def get_arg(lens:int) -> Tuple[int, int, int]:
while True:
a = int(input('a:'))
b = int(input('b:'))
mod = get_prime(lens)
if (4 * (a ** 3) + 27 * (b ** 2)) % mod == 0:
print('Is not correct number.')
else:
break
return a, b, mod
def xor_key(data: int, selfkey: Tuple[int, int]) -> int:
return data ^ selfkey[0] ^ selfkey[1]
def is_prime_of_miller_rabin_test(n: int, trials_time: int = 5) -> bool:
def test_prime_in_100(n: int) -> bool:
prime_list = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
for i in prime_list:
if n % i == 0:
return True
else:
return False
def convert_n_to_sd(n: int) -> Tuple[int, int]:
# n-1 convert to (2^s)*d
s = 0
d = n - 1
while True:
quotient, remainder = divmod(d, 2)
if remainder == 1:
return s, d
s += 1
d = quotient
def test_prime_in_miller_rabin(a: int, d: int, n: int, s: int):
if pow(a, d, n) == 1:
return False
for i in range(s):
if pow(a, 2**i*d, n) == n-1:
return False
return True
if test_prime_in_100(n):
return False
s, d = convert_n_to_sd(n)
for _ in range(trials_time):
a = random.randint(100, n)
if test_prime_in_miller_rabin(a, d, n, s):
return False
return True
def get_prime(lens: int = 30):
while True:
prime = random.randint(10**(lens-1), 10**lens-1)
if len(str(prime)) != lens:
continue
elif prime & 1 == 0:
prime += 1
if is_prime_of_miller_rabin_test(prime):
return prime
def eccdh():
data = input('輸入訊息:')
lens = int(input('金鑰長度:'))
a, b, mod = get_arg(lens+1)
g, n = gen_g(a, b, mod, lens)
a_private, a_public = gen_key(g, n, a, mod)
b_private, b_public = gen_key(g, n, a, mod)
print(len(str(g)), "g:", g)
print(len(str(n)), "n:", n)
print(len(str(a_public)), "公開ap:", a_public)
print(len(str(b_public)), "公開bp:", b_public)
print(len(str(a_private)), "私密a:", a_private)
print(len(str(b_private)), "私密b:", b_private)
apbp = get_xg_or_n(g,a_public, b_private+1, a, mod)
bpap = get_xg_or_n(g,b_public, a_private+1, a, mod)
if apbp != bpap:
print("APBP Is Not Equal:", apbp, bpap)
return False
print("=========================")
print("mod",mod)
print(len(str(g)), "g:", g)
print(len(str(n)), "n:", n)
print(len(str(a_public)), "公開ap:", a_public)
print(len(str(b_public)), "公開bp:", b_public)
print(len(str(a_private)), "私密a:", a_private)
print(len(str(b_private)), "私密b:", b_private)
print(len(str(apbp)), "apbp共同金鑰:", apbp)
print(len(str(bpap)), "bpap共同金鑰:", bpap)
print("=========================")
print("文字內容:", data)
origin_plain_text = int.from_bytes(data.encode('utf-8'), 'big')
print("原本文字轉成數字:", origin_plain_text)
cipher_text = xor_key(origin_plain_text, apbp)
print("加密:", cipher_text)
plain_text = xor_key(cipher_text, bpap)
print("解密:", plain_text)
nbytes, rem = divmod(plain_text.bit_length(), 8)
if rem:
nbytes += 1
decrypt_plain_text = plain_text.to_bytes(nbytes, 'big').decode('utf-8')
print("解密後文字內容:", decrypt_plain_text)
def main():
eccdh()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment