Last active
March 5, 2019 05:10
-
-
Save hikenshi/3e624b2fe22db61f9f43de047f638b8c to your computer and use it in GitHub Desktop.
RSA public and private key encrypt decrypt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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