1. 程式人生 > 其它 >rsa資料加密的python實現

rsa資料加密的python實現

技術標籤:python密碼學

目前只是嘗試了p和q在100以內,實現更大的數,需要的改動不大,就不贅述了

from random import randint
from math import sqrt


class rsa():
    def __init__(self):
        self.create()

    def change(self, p, q):
        try:
            assert p * q > 255 and self.isprime(p) and self.isprime(q)  # n應該大於255
            #注:因為一個字串使轉二進位制時得到的01串共16位,
# 一個字串分割成兩個8位的01串,所以m應小於2^8 self.p = p self.q = q self.n = p * q self.fn = (p - 1) * (q - 1) # 尤拉函式 self.e, self.d = self.returnED(self.fn) return True except: return False def create(self):
self.numList = [] n = 100 # 100內選素數 self.getprimelist(n) num1 = len(self.numList) / 2 - 1 self.n = 0 while self.n <= 255: self.p = self.numList[randint(0, int(num1))] self.q = self.numList[randint(0, int(num1)) + int(len(self.numList)
/ 2)] self.n = self.p * self.q self.fn = (self.p - 1) * (self.q - 1)#尤拉函式 self.e, self.d = self.returnED(self.fn) # 明文字串轉二進位制 def isprime(self,num): if num > 1: for i in range(2, int(sqrt(num))+1): if num % i == 0: return False return True else: print('變數有誤,請輸入大於1的整數。') def get_p_bin(self, Texts): """字串轉二進位制 Text:字串 return 字串對應的二進位制的編碼 """ Text_bin = '' for text in Texts: s = ord(text) s_bin = '{:016b}'.format(s) Text_bin = Text_bin + s_bin return Text_bin # 密文字串轉二進位制 def get_c_bin(self, Texts): """字串轉二進位制 Text:字串 return 字串對應的二進位制的編碼 """ Text_bin = '' for text in Texts: s = ord(text) s_bin = '{:08b}'.format(s) Text_bin = Text_bin + s_bin return Text_bin # 二進位制轉字元函式 def bin_str(self, s): '''獲取16位的01串,返回對應的漢字''' try: return chr(int(s, 2)) except: return -1 #求最大公約數 def gcd(self, a, b): """求最大公約數""" c = a % b while c != 0: # 輾轉相除法 a = b b = c c = a % b # 當餘數為0時,迴圈結束 return b #展示 def disp(self): return self.n, self.e, self.p, self.q, self.d, self.fn #獲取素數表 def getprimelist(self, n): """生成小於n的素數表""" primelist = n * [1] # 全1矩陣 primelist[:2] = [0, 0] # 0和1不是素數 for i in range(2, int(sqrt(n))): # 只需要篩選到最大數的平方根即可,比最大數小的合數必然存在比最大數的平方根小的數 if primelist[i] == 1: # 確認除數是素數 for j in range(i * 2, n, i): primelist[j] = 0 # 倍數肯定不是素數 for i in range(n): if primelist[i] == 1: self.numList.append(i) #尤拉法求模逆元 def Euler(self, e, fn): ''' e為d的係數,fn為k的係數ed=1(modfn) ''' if fn == 0: return 1, 0, e else: x, y, q = self.Euler(fn, e % fn) x, y = y, (x - (e // fn) * y) return x, y, q #返回公鑰e和金鑰d def returnED(self, fn): e = randint(10, fn - 1) while self.gcd(e, self.fn) != 1: e = randint(10, fn - 1) d, x, y = self.Euler(e, fn) while d < 0: d = d + fn # print(f'e,d={e},{d}') return e, d #模冪演算法 def powmod(self, a, b, c): """a:底數 b:指數 c:模 """ b_bin = bin(b)[2:] b_bin = b_bin[::-1] M = a ans = 1 for i in range(len(b_bin)): if b_bin[i] == '1': ans = ans * M % c M = (M * M) % c return ans #二進位制字串分割函式 def distribute(self, m): """"給二進位制字串分組""" mL = [] mlen = len(m) i = 0 while 8 * (i + 1) <= mlen: # print(f'm[{i*8}:{(i+1)*8}]:',m[i*8:(i+1)*8]) mL.append(int(m[i * 8:(i + 1) * 8], 2)) i += 1 return mL #加密函式 def encryption(self, text): m = self.get_p_bin(text) # 明文 mL = self.distribute(m)#8位為一組 self.__plaintext = mL c = '' for m in mL: c = c + str(self.powmod(m, self.e, self.n)) + ' ' # 密文,m的e次方冪 #print("已完成c運算, c=", c) self.__ciphertext = c return self.__ciphertext #解密函式 def dencryption(self, texts, flag): '''flag=0字串 flag=2二進位制 flag=10十進位制 flag=16十六進位制 ''' cL = [] if flag == 0: for text in texts: cL.append(int(self.get_c_bin(text),2)) elif flag == 2: texts = list(texts.split(' ')[:-1]) for text in texts: cL.append(int(text, 2)) elif flag == 10: cL = texts.split(' ')[:-1] elif flag == 16: texts = list(texts.split(' ')[:-1]) for text in texts: cL.append(int(text, 16)) m = [] for c in cL: m.append(str(self.powmod(int(c), self.d, self.n))) #print("已完成m運算, m=", m) self.__plaintext = m return self.__plaintext # 以數字形式展示 def showc_in_num(self, n): ''''n代表進位制,目前僅支援2進位制和16進位制''' cstr = '' s_hex = '' s_bin = '' c = self.__ciphertext if n == 2: for i in c.split(' ')[:-1]: s_bin = s_bin + '{:b}'.format(int(i)) + ' ' return s_bin elif n == 16: s_hex = '' for i in c.split(' ')[:-1]: s_hex = s_hex + '{:x}'.format(int(i)) + ' ' return s_hex elif n == 10: return c else: return '請期待後續版本,感謝您的信賴' # 明文以文字形式展示 def show_mtext(self): '''明文''' M = self.__plaintext m_text = '' for i in range(len(M)//2): mystr = '{:08b}{:08b}'.format(int(M[2*i]),int(M[2*i+1])) m_text = m_text+self.bin_str(mystr) return m_text # 密文以文字形式展示 def show_ctext(self): '''密文''' C = self.__ciphertext C = C.split(' ')[:-1] c_text = '' for i in range(len(C)): mystr= '{:016b}'.format(int(C[i])) c_text = c_text + self.bin_str(mystr) return c_text if __name__ == '__main__': R = rsa() print(R.change(1051,1009)) text = '面朝大海,春暖花開!!' R.encryption(text) c = R.show_ctext() print('c = ',c) R.dencryption(c, 0) print('m = ',R.show_mtext())

結果
在這裡插入圖片描述