45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173 | class RSA:
"""
This class generate public key based on RSA algorithm
Attributes:
p: it's the prime number for generating the modulus
q: it's the second prime number for the modulus
public: Object of the RSAKey which is the public key
private: Object of the RSAKey for the private key
"""
def __init__(self):
"""
Build a RSA Key
"""
self._p = None
self._q = None
self._public = None
self._private = None
def generateKeys(self, size=512):
"""
This function generate both public and private keys
Args:
size: It's the size of the key and must be multiple of 64
"""
# p and q must be coprime
self._p = getPrimeNumber(size)
self._q = getPrimeNumber(size)
# compute n = pq
n = self._p * self._q
phin = (self._p - 1) * (self._q - 1)
# e must be coprime with phi(n)
# According to the FIPS 186-5, the public key exponent must be odd
# and the minimum size is 65536 (Cf. Section 5.4 PKCS #1)
# https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
e = 65535 # Works
for i in range(2, phin - 1):
if gcd(phin, e) == 1:
break
e += 1
# print(gcd(phin, e))
self._public = RSAKey(e, n, getsizeof(e))
# d is the reverse modulo of phi(n)
# d = self._inverseModular(e, phin)
d = pow(e, -1, phin) # Works in python 3.8
self._private = RSAKey(d, n, getsizeof(d))
@property
def e(self):
return self._public.key
@property
def d(self):
return self._private.key
@property
def n(self):
return self._public.modulus
@property
def p(self):
return self._p
@property
def q(self):
return self._q
def encrypt(self, data) -> list:
"""
This function return a list of data encrypted with the public key
Args:
data (str): it's the plaintext which need to be encrypted
Returns:
return a list of the data encrypted, each entries contains the value encoded
"""
dataEncoded = self._str2bin(data)
return list(
pow(int(x), self._public.key, self._public.modulus)
for x in dataEncoded
)
def decrypt(self, data) -> list:
"""
This function return a list decrypted with the private key
Args:
data (str): It's the encrypted data which need to be decrypted
Returns:
Return the list of data uncrypted into plaintext
"""
decrypted = list()
for x in data:
d = pow(x, self._private.key, self._private.modulus)
decrypted.append(chr(d))
return ''.join(decrypted)
def _str2bin(self, data) -> list:
"""
This function convert a string into the unicode value
Args:
data: the string which need to be converted
Returns:
Return a list of unicode values of data
"""
return list(ord(x) for x in data)
def _inverseModular(self, a, n):
"""
This function compute the modular inverse for finding d, the decryption key
Args:
a (Integer): the base of the exponent
n (Integer): the modulus
"""
for b in range(1, n):
if pow(a, b, n) == 1:
inv = b
break
return inv
|