Skip to content

Instantly share code, notes, and snippets.

@hikenshi
Last active March 5, 2019 05:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hikenshi/3e624b2fe22db61f9f43de047f638b8c to your computer and use it in GitHub Desktop.
Save hikenshi/3e624b2fe22db61f9f43de047f638b8c to your computer and use it in GitHub Desktop.
RSA public and private key encrypt decrypt
def kiem_tra_so_nguyen_to_miller_rabin(n):
"""Phương pháp miller - rabin là một phương pháp kiểm tra tính nguyên tố của một số, thực chất là kiểm tra một số không phải là số nguyên tố \
để loại trừ. Cơ sở lý thuyết của phương pháp này như sau: \
1. Định lý nhỏ fermat cho chúng ta biết rằng, nếu n là một số nguyên tố, thì với mọi số a sao cho \
1 <= a < n thì a ^ (n-1) % n = 1.
2. n chắc chắn là số lẻ, vì n lẻ nên n-1 là một số chẵn và có thể biểu đạt dưới dạng: n-1 = d*2^s \
trong đó d là số lẻ và s>0 . \
3. Nhờ hai điều trên, với một số bất kỳ trong khoảng [2, n-2] thì a^(d*2^s) % n phải bằng 1.
4. Một tính chất toán học khác nữa là nếu x^2 % n = 1 thì x^2 -1 % n = 0"""
s = 0
d = n - 1
while d % 2 == 0:
#Theo như điều thứ 2 ở trên ta thử s liên tục cho đến khi d là số lẻ, khi đó ta sẽ được s và d.
d = d // 2
s += 1
#Theo như điều thứ 1 ở trên a^(n-1) % n = 1 tương đương với a^d % n = 1 với 1 <= a < n .
a = 2+ random.randint(1, n-4) # Theo như điều 3 ở trên
x = pow(a,d,n)
if (x == 1 or x == n -1):
return True
while (d != n-1):
x = (x*x) % n
d = d*2
if x == 1:
return False
if x == n -1:
return True
return False
def tao_so_nguyen_to(l):
"""1. If the last digit of the number is 0,2,4,6,8 then the number is not a prime \
2. If sum of the digits of the number is divisble by 3,6 or 9 then the number is not a prime \
3. Subtract the sum of the even digits from the sum of the odd digits. If the result divisible by 11 \
then the number is not a prime"""
random_number = random.getrandbits(int(l))
list_random_number = [int(x) for x in str(random_number)]
last_digit_of_random_number = list_random_number[-1]
truong_hop3 = sum(num for num in list_random_number if not num%2) - sum(num for num in list_random_number if num%2)
if random_number == 2:
return random_number
elif last_digit_of_random_number in [0,2,4,5,6,8]:
return tao_so_nguyen_to(l)
elif sum(list_random_number) % 3 == 0 or sum(list_random_number) % 9 == 0 or sum(list_random_number) % 6 == 0:
return tao_so_nguyen_to(l)
elif truong_hop3 % 11 == 0:
return tao_so_nguyen_to(l)
#for n in range(3, int(random_number**0.5)+2, 2):
# if random_number % n == 0:
# return tao_so_nguyen_to(l)
if kiem_tra_so_nguyen_to_miller_rabin(random_number) == False:
return tao_so_nguyen_to(l)
return random_number
def tao_so_e(phi):
"""số e là số nguyên tố cùng nhau với số phi"""
def gcd(a, b):
while b != 0:
a, b = b, a%b
return a
def coprime(a, b):
return gcd(a, b) == 1
e = random.randrange(1,phi)
if coprime(e, phi) != 1:
return tao_so_e(phi)
return e
def tao_so_d(e, phi):
"""số d là modular inverse của e và phi \
e*d = 1 (mod phi)
1. Thuật toán Euclidean: Dùng để tìm ước số chung lớn nhất (Greatest common divisor) của 2 số a và b \
Ví dụ tìm ước số chung lớn nhất của 210 và 45: \
1.1 Chia 210 cho 45 ta được 4 dư 30. Vậy 210 = 4*45 + 30 \
1.2 Chia 45 cho 30 ta được 1 dư 15. Vậy 45 = 1*30 +15 \
1.3 Chia 30 cho 15 ta được 2 dư 0. Vậy 30 = 2*15 + 0 \
1.4 Vậy 15 chính là ước số chung lớn nhất của 210 và 45.
"""
remainder = 0
while remainder != 1:
quotient, remainder = divmod(phi, e)
def modinv(e, phi):
"""Theo https://crypto.stackexchange.com/a/54479"""
d_old = 0; r_old = phi
d_new = 1; r_new = e
while r_new > 0:
a = r_old // r_new
(d_old, d_new) = (d_new, d_old - a * d_new)
(r_old, r_new) = (r_new, r_old - a * r_new)
return d_old % phi if r_old == 1 else None
def tao_public_key_va_private_key(l):
#tạo số nguyên tố p, q:
p = tao_so_nguyen_to(l/2)
q = tao_so_nguyen_to(l/2)
n = p*q
phi = (p-1)*(q-1)
e = tao_so_e(phi)
d = modinv(e, phi)
#public key is (e, n) , private key is (d, n)
return ((e, n), (d, n))
def encrypt(e, n, message):
cipher_text = [pow(ord(char), e, n) for char in message]
print (''.join(map(lambda x: str(x), cipher_text)))
return cipher_text
def decrypt(d, n, cipher_text):
message = [chr(pow(char, d, n)) for char in cipher_text]
print (''.join(message))
return ''join(message)
def decrypt(d, n, cipher_text):
cipher_text = int(cipher_text)
message_numbers = pow(cipher_text, d, n)
def main():
l = int(input("Vui lòng nhập số bit cần mã hoá RSA. (Ví dụ 128, 256, 512): "))
print("Đang tạo public key và private key ...")
public, private = tao_public_key_va_private_key(l)
print("Public key : ", public , "\nPrivate key : ", private)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment