色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術(shù)文章
文章詳情頁

Python 實(shí)現(xiàn)RSA加解密文本文件

瀏覽:3日期:2022-06-30 17:52:41

近來在使用python寫項(xiàng)目,特此記錄一下項(xiàng)目中遇到的文件加解密問題。關(guān)于python版本的加密算法,隨便搜一搜還是可以檢索出來很多的,不過大都是同一篇文章在不同的平臺(tái)來回發(fā)布,或者就是轉(zhuǎn)載,而且例舉的都是最簡單的情況,那么,實(shí)際項(xiàng)目中使用的話,肯定會(huì)比這個(gè)要稍微復(fù)雜一些,比如我的需求就是要加密一個(gè)使用mysqldump出來的數(shù)據(jù)庫腳本文件,直接拿網(wǎng)上的例子過來調(diào)用肯定是不行的,所以不得不自己研究了一番,特此記錄。

RSA算法什么是RSA算法?

項(xiàng)目選型的算法是RSA非對(duì)稱加密算法,關(guān)于這個(gè)算法不做過多的解釋,咱們劃重點(diǎn):

公鑰用于加密 私鑰用于解密 len_in_byte(raw_data) = len_in_bit(key)/8 -11,如 1024bit 的密鑰,一次能加密的內(nèi)容長度為 1024/8 -11 = 117 byte為何要減去11個(gè)byte?

因?yàn)槲覀兪褂玫氖荘KCS1Padding占用了11個(gè)byte,那么它能加密的明文長度就必須減去這11個(gè)byte

可能會(huì)遇到什么問題?

基于以上三點(diǎn),我們大概可以知道要完成文件加解密,我們可能會(huì)遇到什么問題?

一次性加密明文的長度是和密鑰長度有關(guān)系的,那么我們要加密一個(gè)文件,不能一次性將文本內(nèi)容讀取出來,然后加密如果文件很大,我們也不可能將文件內(nèi)容一次性讀取到內(nèi)存當(dāng)中,可能會(huì)直接導(dǎo)致服務(wù)器無法響應(yīng)其他請(qǐng)求,這肯定是不合理的文本被加密之后,回頭解密,如果讀取的長度有差異勢(shì)必導(dǎo)致解密失敗,那么這個(gè)數(shù)據(jù)庫備份文件就廢了,這個(gè)就比較危險(xiǎn)了

Do It

安裝依賴,python版本3.7.4

pip install pycryptodomex -i https://pypi.tuna.tsinghua.edu.cn/simple/

導(dǎo)入模塊:

import base64from Cryptodome import Randomfrom Cryptodome.PublicKey import RSAfrom Cryptodome.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5from Cryptodome.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5

生成公鑰+私鑰,注意這里我們生成的公鑰長度是1024bit

# 偽隨機(jī)數(shù)生成器random_generator = Random.new().read# rsa算法生成實(shí)例rsa = RSA.generate(1024, random_generator)private_pem = str(rsa.exportKey(), encoding='utf-8')with open('client-private.pem', 'w') as f: f.write(private_pem) public_pem = str(rsa.publickey().exportKey(), encoding='utf-8')with open('client-public.pem', 'w') as f: f.write(public_pem)’’’

加密,這里對(duì)傳入的明文長度做了切分,因?yàn)槲覀兩傻拿荑€長度為1024bit,所以我們一次加密的明文長度不能超過117個(gè)byte

def rsa_encrypt(plaintext, pub_key): ’’’ rsa 加密 :param plaintext: 明文 :param pub_key:公鑰 ’’’ message = plaintext.encode('utf-8') length = len(message) default_length = 117 # 1024/8 - 11 1024為密鑰長度 rsakey = RSA.importKey(pub_key) cipher = Cipher_pkcs1_v1_5.new(rsakey) # 不需要切分 if length <= default_length:return default_rsa_encrypt(cipher, message) # 需要切分 offset = 0 result = [] while length - offset > 0:if length - offset > default_length: result.append(default_rsa_encrypt(cipher, message[offset:offset+default_length]))else: result.append(default_rsa_encrypt(cipher, message[offset:]))offset += default_length return 'n'.join(result) def default_rsa_encrypt(cipher, message): ciphertext = base64.b64encode(cipher.encrypt(message)) # print(b'ciphertext:'+ciphertext) ciphertext_decode = ciphertext.decode('utf-8') # print('ciphertext_decode:'+ciphertext_decode) return ciphertext_decode

解密

def rsa_decrypt(ciphertext, priv_key): ’’’ rsa 解密 :param ciphertext:密文 :param priv_key:私鑰 ’’’ message = base64.b64decode(ciphertext) length = len(message) default_length = 128 rsakey = RSA.importKey(priv_key) cipher = Cipher_pkcs1_v1_5.new(rsakey) if length <= default_length:return default_rsa_decrypt(cipher, message) # 需要分段 offset = 0 result = [] while length - offset > 0:if length - offset > default_length: result.append(rsa_decrypt(cipher, message[offset:offset+default_length]))else: result.append(rsa_decrypt(cipher, message[offset:]))offset += default_length decode_message = [x.decode('utf-8') for x in result] return ''.join(decode_message) def default_rsa_decrypt(cipher, message): plaintext = cipher.decrypt(message, random_generator) # print(b'plaintext:'+plaintext) plaintext_decode = plaintext.decode('utf-8') # print('plaintext_decode:'+plaintext_decode) return plaintext_decode

加解密文件,考慮開頭我們提出的問題,采用了逐行讀取,逐行加密,加密后密文也逐行寫入

def rsa_encrypt_file(file_path, save_path, pub_key): ’’’ rsa 加密文件 :param file_path:需要加密文件路徑 :param save_path:加密之后存放的文件路徑 :param pub_key:公鑰 ’’’ with open(file_path, 'r', encoding='utf-8') as f:line = f.readline() # 讀取一行while line: context = rsa_encrypt(line, pub_key) # 加密切割后的字符 with open(save_path, 'a', encoding='utf-8') as w:w.write(context+'n')line = f.readline()def rsa_decrypt_file(file_path,save_path,priv_key): ’’’ rsa 解密文件 :file_path:需要解密的文件路徑 :save_path:解密之后存放的文件路徑 :priv_key:私鑰 ’’’ with open(file_path,'r',encoding='utf-8') as f:line = f.readline()while line: context = rsa_decrypt(line.strip('n'),priv_key) with open(save_path,'a',encoding='utf-8') as w:w.write(context) line = f.readline()

測(cè)試,一開始我使用的是自己隨便輸入的一行很長的數(shù)字文本,親測(cè)沒有問題,但是當(dāng)我直接使用我的數(shù)據(jù)庫腳本文件的時(shí)候,加密可以成功,但是會(huì)遇到解密后解碼失敗的情況,當(dāng)時(shí)百思不得其解,我以為是字符集的問題,于是我將utf-8,換成了gb2312,加解密成功了,當(dāng)時(shí)心花怒放,直到我重新加解密了另一個(gè)備份文件,又遇到解碼失敗,當(dāng)時(shí)就睡不著覺了~

直到我看到了這句話不完整的多字節(jié)序列(incomplete multibyte sequence)我瞬間明白了,因?yàn)槲业哪_本文件中含有中文,utf8 編碼一個(gè)漢字是3個(gè)byte,gb2312編碼一個(gè)漢字是2個(gè)byte,只要是多字節(jié),那么做切割的時(shí)候,就有可能一個(gè)漢字被切割成了兩部分,那么自然會(huì)導(dǎo)致無法解碼成正確的漢字了,問題已經(jīng)明了,就看怎么解決了。

因?yàn)槭悄_本文件,處理不好就有可能導(dǎo)致腳本執(zhí)行失敗,最終導(dǎo)致數(shù)據(jù)庫還原失敗,這就違背項(xiàng)目初衷了~

所以我想了一個(gè)辦法,先對(duì)每一行文本做字符編碼判斷,超過了117,最后一個(gè)字符就不累計(jì)上去,代碼如下:

def cut_string(message,length = 117): result = [] temp_char = [] for msg in message:#遍歷每一個(gè)字符msg_encode = msg.encode('utf-8')#對(duì)每一個(gè)字符編碼temp_encode = ''.join(temp_char).encode('utf-8')#累計(jì)編碼之后的字節(jié)數(shù)if len(temp_encode) + len(msg_encode) <= length:#如果小于約定的長度,加添加入結(jié)果集 temp_char.append(msg)else:#如果已經(jīng)超過了約定的長度,就添加入下一個(gè)結(jié)果集 result.append(''.join(temp_char)) temp_char.clear() temp_char.append(msg) result.append(''.join(temp_char)) return result

加密方法需要重新調(diào)整一下:

def rsa_encrypt_file(file_path,save_path,pub_key): ’’’ rsa 加密文件 :param file_path:需要加密文件路徑 :param save_path:加密之后存放的文件路徑 :param pub_key:公鑰 ’’’ with open(file_path,'r',encoding='utf-8') as f:line = f.readline() #讀取一行while line: cut_lines = cut_string(line) # 切割字符 保證漢字不被切割 for cut_line in cut_lines:context = rsa_encrypt(cut_line,pub_key) #加密切割后的字符with open(save_path,'a',encoding='utf-8') as w: w.write(context+'n') line = f.readline()

到此問題就已經(jīng)解決了,其實(shí)有了這個(gè)cut_string方法之后,之前寫的加解密方法中不需要再做切分,但是代碼保留。

上面的方法,加解密的效率非常的低,因?yàn)槭侵鹦屑咏饷埽粋€(gè)300M的腳本文件,加密完成耗時(shí)40分鐘,這個(gè)實(shí)在是太難受了,所以調(diào)整了策略,先壓縮再加密,所以就涉及到二進(jìn)制文件的讀取與寫入,最后的實(shí)現(xiàn)代碼如下:

def rsa_encrypt_binfile(file_path,save_path,pub_key): ’’’ rsa 加密二進(jìn)制文件 :param file_path:需要加密文件路徑 :param save_path:加密之后存放的文件路徑 :param pub_key:公鑰 ’’’ with open(file_path, ’rb’) as f: message = f.read() length = len(message) default_length = 117 # 1024/8 - 11 1024為密鑰長度 rsakey = RSA.importKey(pub_key) cipher = Cipher_pkcs1_v1_5.new(rsakey) # 不需要切分 result = [] if length <= default_length: result.append(base64.b64encode(cipher.encrypt(message))) # 需要切分 offset = 0 while length - offset > 0: if length - offset > default_length: result.append(base64.b64encode(cipher.encrypt(message[offset:offset+default_length]))) else: result.append(base64.b64encode(cipher.encrypt(message[offset:]))) offset += default_length with open(save_path,'ab+') as w: for ciphertext in result: ciphertext += b'n' w.write(ciphertext)

def rsa_decrypt_binfile(file_path,save_path,priv_key): ’’’ rsa 解密二進(jìn)制文件 :file_path:需要解密的文件路徑 :save_path:解密之后存放的文件路徑 :priv_key:私鑰 ’’’ with open(file_path,'rb') as f: line = f.readline() while line: message = base64.b64decode(line.strip(b'n')) rsakey = RSA.importKey(priv_key) cipher = Cipher_pkcs1_v1_5.new(rsakey) plaintext = cipher.decrypt(message, random_generator) with open(save_path, ’ab+’) as w: #追加寫入w.write(plaintext) line = f.readline()

以上就是Python 實(shí)現(xiàn)RSA加解密文本文件的詳細(xì)內(nèi)容,更多關(guān)于python rsa加解密的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 日本在线视频免费看 | 国产午夜亚洲精品第一区 | f性欧美 | 男人的亚洲天堂 | 成人合成mv福利视频网站 | 午夜三级成人三级 | 亚洲国产99 | 国产一区亚洲欧美成人 | 毛片在线播放a | 国产日韩欧美在线 | 经典国产乱子伦精品视频 | 玖玖色视频 | 欧美在线播放成人免费 | 亚洲免费在线看 | a级男女性高爱潮高清试 | 97国产精品视频观看一 | 欧美日韩精品一区二区三区视频在线 | 免费高清欧美一区二区视频 | tom影院亚洲国产 | 高清成人爽a毛片免费网站 高清大学生毛片一级 | 日韩精品在线播放 | 亚洲人成在线播放网站岛国 | 一男一女的一级毛片 | 欧美一级人与动毛片免费播放 | 欧美色性| 偷拍视频一区在线观看 | 99精品视频一区在线视频免费观看 | 我要看欧美精品一级毛片 | 日韩一级特黄毛片在线看 | 日本三级欧美三级 | 久久久久亚洲香蕉网 | 国产三级小视频在线观看 | 老外一级毛片免费看 | 日本一区二区高清不卡 | 长腿校花被啪到腿软视频 | 性刺激欧美三级在线现看中文 | 欧美日韩在线观看区一二 | 三级毛片基地 | 国内免费视频成人精品 | 成人软件18免费网站 | 国产免费资源 |