如何用Python实现RSA加密解密长篇文本文件?

2026-04-20 06:592阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2427个文字,预计阅读时间需要10分钟。

如何用Python实现RSA加密解密长篇文本文件?

在使用Python开发项目时,记录下项目中遇到的文件加密问题。关于Python版本的加密算法,很多资源可供查找。多数加密算法的原理和实现可以在多个平台上找到详细的文档和教程。以下是一些常见的Python加密算法资源:

1. Python官方文档:提供了加密模块`cryptography`的详细文档,包括算法原理和实现。

2.Stack Overflow:在这个问答社区中,可以搜索到许多关于Python加密算法的问题和解决方案。

3.GitHub:在GitHub上搜索,可以找到许多开源的加密库和项目,例如`pycryptodome`。

4.博客和教程网站:如Medium、Dev.to等,有许多关于Python加密的教程和文章。

以下是一个简单的加密和解密示例代码:

python

from Crypto.Cipher import AESfrom Crypto.Util.Padding import pad, unpadfrom Crypto.Random import get_random_bytes

生成密钥key=get_random_bytes(16) # AES-128位密钥

创建加密器实例cipher=AES.new(key, AES.MODE_CBC)

待加密的数据data=bHello, this is a secret message!

如何用Python实现RSA加密解密长篇文本文件?

填充数据以符合块大小padded_data=pad(data, AES.block_size)

加密数据encrypted_data=cipher.encrypt(padded_data)

解密数据decipher=AES.new(key, AES.MODE_CBC, cipher.iv)decrypted_data=unpad(decipher.decrypt(encrypted_data), AES.block_size)

print(Encrypted:, encrypted_data.hex())print(Decrypted:, decrypted_data)

这段代码使用了AES加密算法,并展示了如何生成密钥、加密数据、解密数据。在实际应用中,还需要考虑密钥的安全存储和传输。

近来在使用python写项目,特此记录一下项目中遇到的文件加解密问题。
关于python版本的加密算法,随便搜一搜还是可以检索出来很多的,不过大都是同一篇文章在不同的平台来回发布,或者就是转载,而且例举的都是最简单的情况,那么,实际项目中使用的话,肯定会比这个要稍微复杂一些,比如我的需求就是要加密一个使用mysqldump出来的数据库脚本文件,直接拿网上的例子过来调用肯定是不行的,所以不得不自己研究了一番,特此记录。

RSA算法

什么是RSA算法?

项目选型的算法是RSA非对称加密算法,关于这个算法不做过多的解释,咱们划重点:

  • 公钥用于加密
  • 私钥用于解密
  • len_in_byte(raw_data) = len_in_bit(key)/8 -11,如 1024bit 的密钥,一次能加密的内容长度为 1024/8 -11 = 117 byte

为何要减去11个byte?

因为我们使用的是PKCS1Padding占用了11个byte,那么它能加密的明文长度就必须减去这11个byte

可能会遇到什么问题?

基于以上三点,我们大概可以知道要完成文件加解密,我们可能会遇到什么问题?

一次性加密明文的长度是和密钥长度有关系的,那么我们要加密一个文件,不能一次性将文本内容读取出来,然后加密
如果文件很大,我们也不可能将文件内容一次性读取到内存当中,可能会直接导致服务器无法响应其他请求,这肯定是不合理的
文本被加密之后,回头解密,如果读取的长度有差异势必导致解密失败,那么这个数据库备份文件就废了,这个就比较危险了

Do It

安装依赖,python版本3.7.4

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

导入模块:

importbase64 fromCryptodomeimportRandom fromCryptodome.PublicKeyimportRSA fromCryptodome.CipherimportPKCS1_v1_5asCipher_pkcs1_v1_5 fromCryptodome.SignatureimportPKCS1_v1_5asSignature_pkcs1_v1_5

生成公钥+私钥,注意这里我们生成的公钥长度是1024bit

#伪随机数生成器 random_generator=Random.new().read #rsa算法生成实例 rsa=RSA.generate(1024,random_generator) private_pem=str(rsa.exportKey(),encoding="utf-8") withopen("client-private.pem","w")asf: f.write(private_pem) public_pem=str(rsa.publickey().exportKey(),encoding="utf-8") withopen("client-public.pem","w")asf: f.write(public_pem)'''

加密,这里对传入的明文长度做了切分,因为我们生成的密钥长度为1024bit,所以我们一次加密的明文长度不能超过117个byte

defrsa_encrypt(plaintext,pub_key): ''' rsa加密 :paramplaintext:明文 :parampub_key:公钥 ''' message=plaintext.encode("utf-8") length=len(message) default_length=117#1024/8-111024为密钥长度 rsakey=RSA.importKey(pub_key) cipher=Cipher_pkcs1_v1_5.new(rsakey) #不需要切分 iflength<=default_length: returndefault_rsa_encrypt(cipher,message) #需要切分 offset=0 result=[] whilelength-offset>0: iflength-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) defdefault_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) returnciphertext_decode

解密

defrsa_decrypt(ciphertext,priv_key): ''' rsa解密 :paramciphertext:密文 :parampriv_key:私钥 ''' message=base64.b64decode(ciphertext) length=len(message) default_length=128 rsakey=RSA.importKey(priv_key) cipher=Cipher_pkcs1_v1_5.new(rsakey) iflength<=default_length: returndefault_rsa_decrypt(cipher,message) #需要分段 offset=0 result=[] whilelength-offset>0: iflength-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")forxinresult] return"".join(decode_message) defdefault_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) returnplaintext_decode

加解密文件,考虑开头我们提出的问题,采用了逐行读取,逐行加密,加密后密文也逐行写入

defrsa_encrypt_file(file_path,save_path,pub_key): ''' rsa加密文件 :paramfile_path:需要加密文件路径 :paramsave_path:加密之后存放的文件路径 :parampub_key:公钥 ''' withopen(file_path,"r",encoding="utf-8")asf: line=f.readline()#读取一行 whileline: context=rsa_encrypt(line,pub_key)#加密切割后的字符 withopen(save_path,"a",encoding="utf-8")asw: w.write(context+"\n") line=f.readline() defrsa_decrypt_file(file_path,save_path,priv_key): ''' rsa解密文件 :file_path:需要解密的文件路径 :save_path:解密之后存放的文件路径 :priv_key:私钥 ''' withopen(file_path,"r",encoding="utf-8")asf: line=f.readline() whileline: context=rsa_decrypt(line.strip("\n"),priv_key) withopen(save_path,"a",encoding="utf-8")asw: w.write(context) line=f.readline()

测试,一开始我使用的是自己随便输入的一行很长的数字文本,亲测没有问题,但是当我直接使用我的数据库脚本文件的时候,加密可以成功,但是会遇到解密后解码失败的情况,当时百思不得其解,我以为是字符集的问题,于是我将utf-8,换成了gb2312,加解密成功了,当时心花怒放,直到我重新加解密了另一个备份文件,又遇到解码失败,当时就睡不着觉了~

直到我看到了这句话不完整的多字节序列(incomplete multibyte sequence)我瞬间明白了,因为我的脚本文件中含有中文,utf8 编码一个汉字是3个byte,gb2312编码一个汉字是2个byte,只要是多字节,那么做切割的时候,就有可能一个汉字被切割成了两部分,那么自然会导致无法解码成正确的汉字了,问题已经明了,就看怎么解决了。

因为是脚本文件,处理不好就有可能导致脚本执行失败,最终导致数据库还原失败,这就违背项目初衷了~

所以我想了一个办法,先对每一行文本做字符编码判断,超过了117,最后一个字符就不累计上去,代码如下:

defcut_string(message,length=117): result=[] temp_char=[] formsginmessage:#遍历每一个字符 msg_encode=msg.encode("utf-8")#对每一个字符编码 temp_encode="".join(temp_char).encode("utf-8")#累计编码之后的字节数 iflen(temp_encode)+len(msg_encode)<=length:#如果小于约定的长度,加添加入结果集 temp_char.append(msg) else:#如果已经超过了约定的长度,就添加入下一个结果集 result.append("".join(temp_char)) temp_char.clear() temp_char.append(msg) result.append("".join(temp_char)) returnresult

加密方法需要重新调整一下:

defrsa_encrypt_file(file_path,save_path,pub_key): ''' rsa加密文件 :paramfile_path:需要加密文件路径 :paramsave_path:加密之后存放的文件路径 :parampub_key:公钥 ''' withopen(file_path,"r",encoding="utf-8")asf: line=f.readline()#读取一行 whileline: cut_lines=cut_string(line)#切割字符保证汉字不被切割 forcut_lineincut_lines: context=rsa_encrypt(cut_line,pub_key)#加密切割后的字符 withopen(save_path,"a",encoding="utf-8")asw: w.write(context+"\n") line=f.readline()

到此问题就已经解决了,其实有了这个cut_string方法之后,之前写的加解密方法中不需要再做切分,但是代码保留。

上面的方法,加解密的效率非常的低,因为是逐行加解密,一个300M的脚本文件,加密完成耗时40分钟,这个实在是太难受了,所以调整了策略,先压缩再加密,所以就涉及到二进制文件的读取与写入,最后的实现代码如下:

def rsa_encrypt_binfile(file_path,save_path,pub_key): ''' rsa 加密二进制文件 :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 解密二进制文件 :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 实现RSA加解密文本文件的详细内容,更多关于python rsa加解密的资料请关注易盾网络其它相关文章!

本文共计2427个文字,预计阅读时间需要10分钟。

如何用Python实现RSA加密解密长篇文本文件?

在使用Python开发项目时,记录下项目中遇到的文件加密问题。关于Python版本的加密算法,很多资源可供查找。多数加密算法的原理和实现可以在多个平台上找到详细的文档和教程。以下是一些常见的Python加密算法资源:

1. Python官方文档:提供了加密模块`cryptography`的详细文档,包括算法原理和实现。

2.Stack Overflow:在这个问答社区中,可以搜索到许多关于Python加密算法的问题和解决方案。

3.GitHub:在GitHub上搜索,可以找到许多开源的加密库和项目,例如`pycryptodome`。

4.博客和教程网站:如Medium、Dev.to等,有许多关于Python加密的教程和文章。

以下是一个简单的加密和解密示例代码:

python

from Crypto.Cipher import AESfrom Crypto.Util.Padding import pad, unpadfrom Crypto.Random import get_random_bytes

生成密钥key=get_random_bytes(16) # AES-128位密钥

创建加密器实例cipher=AES.new(key, AES.MODE_CBC)

待加密的数据data=bHello, this is a secret message!

如何用Python实现RSA加密解密长篇文本文件?

填充数据以符合块大小padded_data=pad(data, AES.block_size)

加密数据encrypted_data=cipher.encrypt(padded_data)

解密数据decipher=AES.new(key, AES.MODE_CBC, cipher.iv)decrypted_data=unpad(decipher.decrypt(encrypted_data), AES.block_size)

print(Encrypted:, encrypted_data.hex())print(Decrypted:, decrypted_data)

这段代码使用了AES加密算法,并展示了如何生成密钥、加密数据、解密数据。在实际应用中,还需要考虑密钥的安全存储和传输。

近来在使用python写项目,特此记录一下项目中遇到的文件加解密问题。
关于python版本的加密算法,随便搜一搜还是可以检索出来很多的,不过大都是同一篇文章在不同的平台来回发布,或者就是转载,而且例举的都是最简单的情况,那么,实际项目中使用的话,肯定会比这个要稍微复杂一些,比如我的需求就是要加密一个使用mysqldump出来的数据库脚本文件,直接拿网上的例子过来调用肯定是不行的,所以不得不自己研究了一番,特此记录。

RSA算法

什么是RSA算法?

项目选型的算法是RSA非对称加密算法,关于这个算法不做过多的解释,咱们划重点:

  • 公钥用于加密
  • 私钥用于解密
  • len_in_byte(raw_data) = len_in_bit(key)/8 -11,如 1024bit 的密钥,一次能加密的内容长度为 1024/8 -11 = 117 byte

为何要减去11个byte?

因为我们使用的是PKCS1Padding占用了11个byte,那么它能加密的明文长度就必须减去这11个byte

可能会遇到什么问题?

基于以上三点,我们大概可以知道要完成文件加解密,我们可能会遇到什么问题?

一次性加密明文的长度是和密钥长度有关系的,那么我们要加密一个文件,不能一次性将文本内容读取出来,然后加密
如果文件很大,我们也不可能将文件内容一次性读取到内存当中,可能会直接导致服务器无法响应其他请求,这肯定是不合理的
文本被加密之后,回头解密,如果读取的长度有差异势必导致解密失败,那么这个数据库备份文件就废了,这个就比较危险了

Do It

安装依赖,python版本3.7.4

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

导入模块:

importbase64 fromCryptodomeimportRandom fromCryptodome.PublicKeyimportRSA fromCryptodome.CipherimportPKCS1_v1_5asCipher_pkcs1_v1_5 fromCryptodome.SignatureimportPKCS1_v1_5asSignature_pkcs1_v1_5

生成公钥+私钥,注意这里我们生成的公钥长度是1024bit

#伪随机数生成器 random_generator=Random.new().read #rsa算法生成实例 rsa=RSA.generate(1024,random_generator) private_pem=str(rsa.exportKey(),encoding="utf-8") withopen("client-private.pem","w")asf: f.write(private_pem) public_pem=str(rsa.publickey().exportKey(),encoding="utf-8") withopen("client-public.pem","w")asf: f.write(public_pem)'''

加密,这里对传入的明文长度做了切分,因为我们生成的密钥长度为1024bit,所以我们一次加密的明文长度不能超过117个byte

defrsa_encrypt(plaintext,pub_key): ''' rsa加密 :paramplaintext:明文 :parampub_key:公钥 ''' message=plaintext.encode("utf-8") length=len(message) default_length=117#1024/8-111024为密钥长度 rsakey=RSA.importKey(pub_key) cipher=Cipher_pkcs1_v1_5.new(rsakey) #不需要切分 iflength<=default_length: returndefault_rsa_encrypt(cipher,message) #需要切分 offset=0 result=[] whilelength-offset>0: iflength-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) defdefault_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) returnciphertext_decode

解密

defrsa_decrypt(ciphertext,priv_key): ''' rsa解密 :paramciphertext:密文 :parampriv_key:私钥 ''' message=base64.b64decode(ciphertext) length=len(message) default_length=128 rsakey=RSA.importKey(priv_key) cipher=Cipher_pkcs1_v1_5.new(rsakey) iflength<=default_length: returndefault_rsa_decrypt(cipher,message) #需要分段 offset=0 result=[] whilelength-offset>0: iflength-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")forxinresult] return"".join(decode_message) defdefault_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) returnplaintext_decode

加解密文件,考虑开头我们提出的问题,采用了逐行读取,逐行加密,加密后密文也逐行写入

defrsa_encrypt_file(file_path,save_path,pub_key): ''' rsa加密文件 :paramfile_path:需要加密文件路径 :paramsave_path:加密之后存放的文件路径 :parampub_key:公钥 ''' withopen(file_path,"r",encoding="utf-8")asf: line=f.readline()#读取一行 whileline: context=rsa_encrypt(line,pub_key)#加密切割后的字符 withopen(save_path,"a",encoding="utf-8")asw: w.write(context+"\n") line=f.readline() defrsa_decrypt_file(file_path,save_path,priv_key): ''' rsa解密文件 :file_path:需要解密的文件路径 :save_path:解密之后存放的文件路径 :priv_key:私钥 ''' withopen(file_path,"r",encoding="utf-8")asf: line=f.readline() whileline: context=rsa_decrypt(line.strip("\n"),priv_key) withopen(save_path,"a",encoding="utf-8")asw: w.write(context) line=f.readline()

测试,一开始我使用的是自己随便输入的一行很长的数字文本,亲测没有问题,但是当我直接使用我的数据库脚本文件的时候,加密可以成功,但是会遇到解密后解码失败的情况,当时百思不得其解,我以为是字符集的问题,于是我将utf-8,换成了gb2312,加解密成功了,当时心花怒放,直到我重新加解密了另一个备份文件,又遇到解码失败,当时就睡不着觉了~

直到我看到了这句话不完整的多字节序列(incomplete multibyte sequence)我瞬间明白了,因为我的脚本文件中含有中文,utf8 编码一个汉字是3个byte,gb2312编码一个汉字是2个byte,只要是多字节,那么做切割的时候,就有可能一个汉字被切割成了两部分,那么自然会导致无法解码成正确的汉字了,问题已经明了,就看怎么解决了。

因为是脚本文件,处理不好就有可能导致脚本执行失败,最终导致数据库还原失败,这就违背项目初衷了~

所以我想了一个办法,先对每一行文本做字符编码判断,超过了117,最后一个字符就不累计上去,代码如下:

defcut_string(message,length=117): result=[] temp_char=[] formsginmessage:#遍历每一个字符 msg_encode=msg.encode("utf-8")#对每一个字符编码 temp_encode="".join(temp_char).encode("utf-8")#累计编码之后的字节数 iflen(temp_encode)+len(msg_encode)<=length:#如果小于约定的长度,加添加入结果集 temp_char.append(msg) else:#如果已经超过了约定的长度,就添加入下一个结果集 result.append("".join(temp_char)) temp_char.clear() temp_char.append(msg) result.append("".join(temp_char)) returnresult

加密方法需要重新调整一下:

defrsa_encrypt_file(file_path,save_path,pub_key): ''' rsa加密文件 :paramfile_path:需要加密文件路径 :paramsave_path:加密之后存放的文件路径 :parampub_key:公钥 ''' withopen(file_path,"r",encoding="utf-8")asf: line=f.readline()#读取一行 whileline: cut_lines=cut_string(line)#切割字符保证汉字不被切割 forcut_lineincut_lines: context=rsa_encrypt(cut_line,pub_key)#加密切割后的字符 withopen(save_path,"a",encoding="utf-8")asw: w.write(context+"\n") line=f.readline()

到此问题就已经解决了,其实有了这个cut_string方法之后,之前写的加解密方法中不需要再做切分,但是代码保留。

上面的方法,加解密的效率非常的低,因为是逐行加解密,一个300M的脚本文件,加密完成耗时40分钟,这个实在是太难受了,所以调整了策略,先压缩再加密,所以就涉及到二进制文件的读取与写入,最后的实现代码如下:

def rsa_encrypt_binfile(file_path,save_path,pub_key): ''' rsa 加密二进制文件 :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 解密二进制文件 :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 实现RSA加解密文本文件的详细内容,更多关于python rsa加解密的资料请关注易盾网络其它相关文章!