点击上方“Python爬虫与数据挖掘”,进行关注

回复“书籍”即可获赠Python从入门到进阶共10本电子书

三分割据纡筹策,万古云霄一羽毛。

前言

加密是指利用某个值(密钥)对明文的数据通过一定的算法变换加密(密文)数据的过程,它的逆向过程叫解密。

业务场景:一般情况下,互联网上流动的数据不会被加密,无法避免这些数据泄露窃取,实际数据上传过程中,为了保证数据不被泄露、实现安全数据传输,出现了各种加密技术,本次主要分享如何通过python来实现非对称加密算法RSA加解密。

RSA算法简介

加密和解密使用相同的密钥叫对称加密方式,而非对称加密算法(公钥加密方式)RSA加密与解密分别用不同的密钥,公钥用于加密,私钥用于解密。

比如发送者S要给接受者R传输报文信息,为了避免信息泄露,秘钥签发者R事先通过RSA加密算法生成秘钥对,并且将公钥事先给到S,私钥则自己保留,S向R传输信息时,先用R提供的公钥加密报文,然后再将报文传输给R,R获取加密后的信息,再通过其单独持有的私钥解密报文,即使报文被窃听,窃听者没有私钥,也无法解密。公钥对外公开的,私钥自己保留,由于公钥是公开的,任何人都能拿到(会同时给到多个人),都可以使用公钥来加密发送伪造内容,因此,验证发送者的身份,确保报文的安全性显得非常重要。

考虑到一种情况:发送者S获取接收者R的公钥时,被中间人A获取到了这个公钥,通过公钥对信息加密,冒充S来给R发篡改的报文,同样R接受信息后也能够通过持有的私钥解密报文数据,接受者无法辨别数据发送者身份,存在报文非法修改风险,为了区分发送者的身份,那么这个时候我们就要用到签名。

签名原理:对报文做摘要,能防止被篡改。发送方对报文原文做加盐hash摘要,把加密原文和摘要一起发送给接收方,接收方解密后,用同样的hash方法计算并比对摘要,就能判断原文是否被篡改。

签名过程:发送者S同样也生成了一对秘钥,事先将公钥给到R,在发送消息之前,先用R给的公钥对报文加密,然后签名使用S自己私钥来签名,最后将加密的消息和签名一起发过去给R,接受者R在接收到发送者S发送的数据后,首先使用S的公钥对签名信息进行验签,确认身份信息,如果确认是发送者S,然后再R才利用私钥对加密消息进行解密,从而隔离非法数据包的接收。

这样一来,发送过程信息被获取,没有R的私钥无法解密信息,即使获取到发送者S的公钥,想要仿造发送信息没有S的私钥无法签名,同理R给S回复信息时,可以通过R的公钥加密,自己的私钥生成签名,S接收到数据使用同样的方式进行解密验证身份。私钥加签,公钥验签,这样就能确保只有私钥持有者也就是发送者能合法发送数据。

加签:

验签:

Python实现RSA加解密相关知识要点

1、首先安装加密库:pip install pycryptodome

python中要使用到crypto相关的库,使用的第三方库是 pycryptodome,其为pycrypto的延伸版本。

  • rsa文档地址:https://stuvel.eu/files/python-rsa-doc/index.html

  • pycryptodome文档地址:https://www.pycryptodome.org/en/latest/src/cipher/classic.html

2、字符串和Bytes互相转换使用encode()和decode()方法

加密与解密操作的时候,要确保我们操作的数据类型是Bytes。

3、生成秘钥对

秘钥对一般由密钥签发者来生成提供。通过RSA校验生成自己的公钥,私钥,这里生成固定的备用。

from Crypto import Random
from Crypto.PublicKey import RSA# 伪随机数生成器
random_gen = Random.new().read# 生成秘钥对实例对象:2048是秘钥的长度
rsa = RSA.generate(2048, random_gen)# 获取私钥,保存到文件
private_pem = rsa.exportKey()
with open('private.pem', 'wb') as f:f.write(private_pem)# 获取公钥保存到文件
public_pem = rsa.publickey().exportKey()
with open('public.pem', 'wb') as f:f.write(public_pem)

生成秘钥对的时候,可以指定生成秘钥的长度,一般推荐使用 1024bit, 1024bit 的 rsa 公钥,加密数据时,最多只能加密 117byte 的数据,数据量超过这个数,则需要对数据进行分段加密;为保证更安全,尽量使用 2048bit ,最多只能加密245byte 长度的数据。

秘钥对生成如下格式:

公钥
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtas/LB41SKhFtu49b7TZ
oiTQ+ABoT6b8REs8PuuE5PZHByA/IXvEGrNl5osOV79OMmgAxiZGirXOfWZMoZuB
7Htu97Fyyh9fc9WLlkaCPbkN6LDp6EEiW+seQbcmJHRSgQUyyzu/T9/x9aA2aoHv
JeRO59kDmYfyoyg5+rFfgzy+YizZWqFRTLV9ZXKecIfAy7Opt3rnc2EaiFDr7/zw
KJmIxOfESwmhmRV1RyMj3O0yFD1xnkZ7ouh+4OExwNjTdUVpoQDz2HaU9QC/tEIX
TyJX36sJSyciLb+8itcfhegnBiNxRYZtwzsq8o9ASBcuXjzZPU7zlVGQTxIK7lWX
PwIDAQAB
-----END PUBLIC KEY-----
私钥
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAtas/LB41SKhFtu49b7TZoiTQ+ABoT6b8REs8PuuE5PZHByA/
IXvEGrNl5osOV79OMmgAxiZGirXOfWZMoZuB7Htu97Fyyh9fc9WLlkaCPbkN6LDp
6EEiW+seQbcmJHRSgQUyyzu/T9/x9aA2aoHvJeRO59kDmYfyoyg5+rFfgzy+YizZ
WqFRTLV9ZXKecIfAy7Opt3rnc2EaiFDr7/zwKJmIxOfESwmhmRV1RyMj3O0yFD1x
nkZ7ouh+4OExwNjTdUVpoQDz2HaU9QC/tEIXTyJX36sJSyciLb+8itcfhegnBiNx
RYZtwzsq8o9ASBcuXjzZPU7zlVGQTxIK7lWXPwIDAQABAoIBAAJSmhN20wItGi/g
dBgH05mympqPhF9/iFpZLRm2CiduDKXT+dEN4FZ7dH74Yfd2O/1oZGYkJ1YiEYdI
T3K1GcalV1uPjbx1OG1Mzb5fA86rnVI1yaMAcWK3RIl2wLD9Ob02wBnM5EFhrbOQ
8YRc4x4nzc7bo/BxEzjJzJMrdGF2cYeVMlASxA7IE09W+FFvPAWLR1nlfx6GoZuJ
edvQtrDxgRPLRluGWRdHmASoYHgONBJmV9NjLeOyGPwK32obdeE2vQLfaghDRvmI
GJ7LAc0yYRS7Aa82/BF8/x/r/BR3o7+bFg1t3n+SFXx8eCUSsBCKL3BNu1HiyWWj
2LGFlp0CgYEAyvC/CThHuAocIp4p7nyB6Wwx0fxxgLvcUtIfP77yOZDm3T2UK6BX
gLEMb7Fpmo6uH39ewubQtSxMrJH20DUA7MyRVJQUiM+bSvJ4jG/T+I1bi7BfVuL9
QDbW+zQvQ9CHZ0ZaijelolSBzMfO6/l4km6zgeM/Wf3ypkvvX+k9VfMCgYEA5SrA
u+rnUpPb1vCBZ+DZrPkA0hYB+N+eZ0wmrM4m0dP6xI084UpU0PEdL+o8FE9azlN7
l7tWtdmx003jy3pnzr6DMMIfgB92bHCfMMPq7ddSbfz6ul/kr67oUtMAdcy+odrY
Ah59+q9oyIeVZLtBKvlzaTp6httwm/kKL2n0UIUCgYEAhFz7rM7JcE8fxLB2Vvdc
YFvSLszBVx6weFBWU2R+Zm+NNHXqg33kNKrFmsATSdyP0zlnHCYhsFlBdTkKywgX
H1vZ2llu/0CxX/PADpENp0rDj9usg2Yvmcdq9pM11LxY5FIt0YK0BKmrs14LJzwi
mRec+zW150NMFYznhx4AhGMCgYAnjF9CjuFo4Nd5mnvan3UxYq9/kgi5GG5PyVaL
T/BnGbwXG4C8KIXGoTW2RSglISS8oq+bmdr2+yCzJKgBP5iWl04wpe+lvshDIpR2
Z/ktHpG9JYFnlJD0uKyjToKv0au8ZvYMN5LqJkdhA/UGM0Kl1fLS4CKxD0G5yRq2
4AQnuQKBgQDEyPS12CtCkOZMCwoONWGlnhsTmwxZJpVbCGmFucpuJagQiIIpHnJq
3LlU9Z3wh09kGFHJlSSzdMkHzZ4/x6ra4zuGObClHju6v3I5sY3/iPw97zDTiq0P
x7f9hR//cY9wnhjbaQkpvNooHXTHL3PZC8AN4Ud+aKzzbwFWrUBYxw==
-----END RSA PRIVATE KEY-----

计算公式如下:秘钥长度/8-11 = 最大加密量(单位:byte)

4、Base64编码

base64 是网络上最常见的用于传输8bit字节代码的编码方式之一,是一种基于64个可见字符来表示二进制数据的方法。用来将非ASCII字符数据转换成ASCII字符的一种方法,特别适合在HTTP协议下快速传输数据。比如邮件,ASCII 控制字符 、中文、图片二进制数据等。

基本原理

base64 将 ASCII 码 或者二进制编码成只包含 A~Z、a~z、0~9、+ 、/ 这64个字符(26个大写字符、26个小写字符、10个数字、+/)。通过3个8bit字节( 3 x 8 = 24 )编码成4个6位字节(4 x 6 = 24),在每个6位字节前补两个0,形成4个8字节形式。

编码规则

base64要求把每3个8bit字节转换为4个6bit的字节,然后把6bit的字节高两位添加为0,组成4个8bit的字节,理论上将比原来长1/3。如果要编码的二进制数据不是3的倍数,数据长度除以3的余数就是2或者1,转换的时候结果不足6位的,用0来填充,之后在6位前面补两个0,转换完空出的结果用 = 来补位,最后保证编码出来的字节为4的倍数。解码的时候,等号会自动被去掉。

注:由于标准的Base64编码后可能出现字符+和斜扛/,+和/在URL中不能直接作为参数,因此,Base64提供了urlsafe_b64encode方法将+和/分别转换为横杠-和下画线_,使用urlsafe_b64decode方法将横杠-和下画线_还原为字符+和斜扛/。

Python实现RSA加解密和签名验签类

本文将RSA加密方法写成一个类,支持包含中文的长字符串分段加解密。

注:经过分段加密的数据,在进行解密的时候我们也要分成多段解密,然后解密之后再进行拼接成原串,加密签名与解密验签注意保持原串一致。

from Crypto import Random
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1_v1_5
import base64
from Crypto.Signature import PKCS1_v1_5 as Sig_pk
from Crypto.Hash import SHAclass RSACipher():'''RSA加密、解密、签名、验签工具类备注:# RSA的加密机制有两种方案一个是RSAES-OAEP,另一个RSAES-PKCS1-v1_5# 对同样的数据,用同样的key进行RSA加密, 每次的输出都会不一样;但是这些加密的结果都能正确的解密'''def read_xml(self,xmlfile):'''读取待加密明文方法'''with open(xmlfile, 'r', encoding="utf-8") as file:# 用open()将XML文件中的内容读取为字符串xmlstr = file.read()print(xmlstr)return xmlstrdef encrypt_file(self,encrypt_file):'''保存加密后密文方法'''with open(encrypt_file, 'rb') as f:message = f.read()return messagedef Encrypt(self, message, publicKeyfile, out_file):'''加密方法:param message: 需要加密的明文:param publicKeyfile: 公钥文件:param out_file: 输出密文:return: 加密后的文本'''with open(publicKeyfile, 'r') as f:publicKey = f.read()pubKey = RSA.importKey(publicKey)cipher = Cipher_PKCS1_v1_5.new(pubKey)message = message.encode()# 分段加密,加密长度byte为8的倍数,最长不超出最大加密量(单位:byte)=秘钥长度/8-11length = len(message)default_length = 245offset = 0res = bytes()while length - offset > 0:if length - offset > default_length:_res = cipher.encrypt(message[offset:offset + default_length])else:_res = cipher.encrypt(message[offset:])offset += default_lengthres += _resencrypt_text=base64.b64encode(res)with open(out_file, 'wb') as f_w:f_w.write(base64.b64encode(res))return encrypt_textdef Decrypt(self,message, privateKeyfile, out_file):'''解密方法:param message: 加密后的密文:param privateKey: 私钥文件:param out_file: 输出明文:return: 解密后的文本'''with open(privateKeyfile, 'r') as f:privateKey = f.read()rsaKey = RSA.importKey(privateKey)cipher = Cipher_PKCS1_v1_5.new(rsaKey)randomGenerator = Random.new().readmessage = base64.b64decode(message.decode())res = []for i in range(0, len(message), 256):res.append(cipher.decrypt((message[i:i + 256]),randomGenerator))plainText = bytes(b"".join(res)).decode()print(plainText)with open(out_file, 'w', encoding='utf-8') as f_w:f_w.write(plainText)return plainTextdef sign(self,message, private_sign_file):'''签名方法:param message: 需要签名的文本:param private_sign_file: 私钥文件:return: 签名信息'''with open(private_sign_file, 'r') as f:private_sign = f.read()message = message.encode()private_key = RSA.importKey(private_sign)# 根据sha算法处理签名内容hash_value = SHA.new(message)# 私钥进行签名signer = Sig_pk.new(private_key)signature = signer.sign(hash_value)result=base64.b64encode(signature).decode()return result # 将签名后的内容,转换为base64编码def verify(self,message,public_sign_file,signature):'''验签方法:param message: 需要验签的文本:param public_sign_file: 公钥文件:param signature: 签名信息:return: 验签结果'''with open(public_sign_file, 'r') as f:public_sign = f.read()signature = base64.b64decode(signature)# 将签名之前的内容进行hash处理public_key = RSA.importKey(public_sign)print(public_key)# 验证签名hash_value = SHA.new(message.encode())verifier = Sig_pk.new(public_key)return verifier.verify(hash_value, signature)if __name__ == '__main__':#创建RSA加密实例rsacipher = RSACipher()xmlfile = r'new1.xml'message=rsacipher.read_xml(xmlfile) #待加密明文encryptFile = "encrypt.txt"  #加密后密文publicKeyfile="rsa.pub" #公钥加密# 加密encrypt_text = rsacipher.Encrypt(message,publicKeyfile,encryptFile)print('加密后:\n%s' % encrypt_text)# 签名private_sign_file="private.pem"  # 私钥签名signature = rsacipher.sign(message,private_sign_file)print('签名:\n%s' % signature)# 解密decryptFile ="deencrypt.txt" #输出解密内容privateFile = "rsa.key"  #私钥解密decrypt_text = rsacipher.Decrypt(encrypt_text,privateFile,decryptFile)print('解密后:\n%s' % decrypt_text)# 验签pubic_sign_file = "public.pem"  # 公钥验签result = rsacipher.verify(decrypt_text,pubic_sign_file,signature)print('验签:\n%s' % result)

文中包含所有源码,自己动手创建两套公钥私钥、测试文本即可,快动手试一下吧。

小伙伴们,快快用实践一下吧!如果在学习过程中,有遇到任何问题,欢迎加我好友,我拉你进Python学习交流群共同探讨学习。

------------------- End -------------------

往期精彩文章推荐:

  • 如何利用Python实现'2021年9月28日'转换位为'2021/9/28'格式?

  • 盘点3种Python网络爬虫过程中的中文乱码的处理方法

  • 一篇文章带你轻松获取女神家庭住址

  • 手把手教你用Python网络爬虫实现上海证券交易所定期报告pdf文件下载(附代码)

欢迎大家点赞,留言,转发,转载,感谢大家的相伴与支持

想加入Python学习群请在后台回复【入群

万水千山总是情,点个【在看】行不行

/今日留言主题/

随便说一两句吧~

如何使用RSA 对数据加解密和签名验签?一篇文章带你搞定相关推荐

  1. Java 实现 RSA 非对称加密算法-加解密和签名验签

    1. 非对称加密算法简介 非对称加密算法又称现代加密算法,是计算机通信安全的基石,保证了加密数据不会被破解.与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密(pr ...

  2. 国密SM4加解密SM2签名验签COM组件DLL

    提供给第三方软件,调用COM组件DLL方式进行实现,如delphi.PB等. 基于C#编写的COM组件DLL,可实现SM2签名验签,SM4加解密,100%适用于黑龙江省国家医保接口中进行应用. 功能包 ...

  3. SM2加解密、签名验签

    导论 SM2是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法,在我们国家商用密码体系中被用来替换RSA算法. 国产SM2算法,是基于ECC的,但二者在签名验签.加密解密过程中或许有些 ...

  4. 讲讲在银联电子支付工作时加解密、签名验签的那些事(纯粹的干货)。

    今天我们来讲讲系统间的交互需要哪些必要的东西才能确保互相通信会没有问题呢? 首先来看看最传统的系统交互,即两者直接互相明文传送,在这种情况下,若是被第三方拦截,会造成不可预估的影响.那么针对这种情况我 ...

  5. C#实现RSA公钥加密私钥解密、私钥加密公钥解密以及Pcks12、X509证书加解密、签名验签

    RSA的私钥签名公钥验签可以见 http://blog.csdn.net/starfd/article/details/51917916,所以这里就没提供对应代码,具体代码如下: using Org. ...

  6. 国密算法SM2加解密_签名验签图形化例子

    点击上方蓝字可直接关注!方便下次阅读.如果对你有帮助,麻烦点个在看或点个赞,感谢~ 国密SM2概述 对国密算法有了解的朋友看到SM2可能会先想到非对称加密,之前的SM4是对称加密.SM4加解密使用的是 ...

  7. python实现RSA加密解密 及 签名验签功能

    本篇写一下python实现RSA的加密解密功能.私钥签名 公钥验签功能. 主要分三部分来介绍 生成私钥和公钥 脚本如下,运行后会生成public.pem(公钥) 和 private.pem(私钥) d ...

  8. RSA密钥生成、加密解密、数据签名验签

    公钥.私钥生成 准备工作,基础的帮助类 使用java代码生成公钥私钥 使用openssl生成公钥私钥 加解密 数据签名及验签 数据加解密及签名验签测试 注意项 公钥.私钥生成 准备工作,基础的帮助类 ...

  9. golang RSA base64 加解密 签名验签

    1.秘钥.加密/签名字符串加密的格式 目前主要见到有hex及base64 (1)hex 针对hex的加解密 import ("encoding/hex" ) hex.DecodeS ...

最新文章

  1. 取得数组中的随机数random.nextInt(index)
  2. 初识片选信号和中断控制器
  3. 干掉MySQL!阿里云MVP专家的分库分表设计,搞得太棒了!
  4. Mysql(五) JDBC
  5. python变量存储 堆与栈内存内存_浅析JS中的堆内存与栈内存
  6. @Transient不起作用的问题
  7. JSONObject,JSONArray,对象,数组互相转化
  8. 汇编语言(王爽)第四版检测点2.2答案
  9. 杭电--1009 C语言实现
  10. 在windows server 2003服务器上提供NTP时间同步服务
  11. hex与bin文件及hex2bin
  12. 如何打开.yml文件
  13. 歌单音乐播放器php源码,thinkphp多风格网页音乐播放器源码
  14. Element概述、入门案例及布局
  15. 十大著名黑客——George Hotz
  16. mysql左连接和右连接_MYSQL 左连接与右连接
  17. MTK机器原始OTA更新方法
  18. 定位“良心优品”,国民手机Z5能否让联想重回辉煌?
  19. (6/300)一阶线性非齐次常微分方程的通解
  20. python代码图片头像_python图像处理-个性化头像

热门文章

  1. 第一次vscode 推送已有代码 到gitee新仓库
  2. 区块链:Hyperledger Fabric环境配置及fabric-sample测试运行
  3. 4、spss做多元线性回归
  4. GDK8——强大的Linux内核调试工具
  5. 数字逻辑基础实验二—时序逻辑电路的设计
  6. 飞腾cpu服务器浪潮信息,推动国产化进程 浪潮发布飞腾服务器
  7. 数学知识复习:三重积分
  8. 阿里云实人认证 人脸识别
  9. 前端微信签名验证工具_微信JS接口签名的生成
  10. 如何开发短信通知和语音功能医院信息系统(HIS系统)