python中的RSA加密与解密实例解析


Posted in Python onNovember 18, 2019

这篇文章主要介绍了python RSA加密与解密实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

什么是RSA:

RSA公开密钥密码体制。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。

在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK。

正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA 密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。

RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,截止2017年被普遍认为是最优秀的公钥方案之一。

SET(Secure Electronic Transaction)协议中要求CA采用2048bits长的密钥,其他实体使用1024比特的密钥。RSA密钥长度随着保密级别提高,增加很快。下表列出了对同一安全级别所对应的密钥长度。

python实现对RSA的加密和解密

Python密码库--Pycrypto

Python良好的生态,对于加密解密技术都有成熟的第三方库。大名鼎鼎的M2Crypto和Pycrypto,前者非常容易使用,可是安装却非常头疼,不同的系统依赖软件的版本还有影响。后者则比较方面,直接使用pip安装即可。

密码技术

为了进行加密以及通信,人们发明了很多公开的算法。对称与非对称算法等。常见的加密方式有RSA, AES等算法。对于选择加密算法,一个常识就是使用公开的算法。一方面是这些算法经过实践检验,另一方面对于破译难度和破译条件破译时间都有预估。对于任何加密算法,都是能破解的,不同在于时间上的投入。

Python密码库--Pycrypto

Python良好的生态,对于加密解密技术都有成熟的第三方库。大名鼎鼎的M2Crypto和Pycrypto,前者非常容易使用,可是安装却非常头疼,不同的系统依赖软件的版本还有影响。后者则比较方面,直接使用pip安装即可。

安装

pip install pycrypto

RSA 密码算法与签名

RSA是一种公钥密码算法,RSA的密文是对代码明文的数字的 E 次方求mod N 的结果。也就是将明文和自己做E次乘法,然后再将其结果除以 N 求余数,余数就是密文。RSA是一个简洁的加密算法。E 和 N 的组合就是公钥(public key)。

对于RSA的解密,即密文的数字的 D 次方求mod N 即可,即密文和自己做 D 次乘法,再对结果除以 N 求余数即可得到明文。D 和 N 的组合就是私钥(private key)。

算法的加密和解密还是很简单的,可是公钥和私钥的生成算法却不是随意的。本文在于使用,对生成秘钥对的算法就暂时忽略。使用 Pycrypto生成秘钥对很简单,我们分别为 Server和Client各生成一对属于自己的秘钥对。

from Crypto import Random
from Crypto.Hash import SHA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5
from Crypto.PublicKey import RSA
 
# 伪随机数生成器
random_generator = Random.new().read
# rsa算法生成实例
rsa = RSA.generate(1024, random_generator)
 
# Server的秘钥对的生成
private_pem = rsa.exportKey()
with open("server-private.pem", "w") as f:
 f.write(private_pem)
 
public_pem = rsa.publickey().exportKey()
with open("server-public.pem", "w") as f:
 f.write(public_pem)
 
# Client的秘钥对的生成
private_pem = rsa.exportKey()
with open("client-private.pem", "w") as f:
 f.write(private_pem)
 
public_pem = rsa.publickey().exportKey()
with open("client-public.pem", "w") as f:
 f.write(public_pem)

所生成的私钥和公钥大概是这样的:

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQC26X6A0WCWiVxdxq3jtm42yDdGbf+99v2zyi0UMVGZfowlnkcW
eMvpz8NBm2UVlrjZpnFr8wFkdHyjFFkq/ilclH3AN4+Xw8Ap7CGJ2jVMyS5h9RRB
Uyf3F4D5Og8789Ywh9HXYyvD/6J62EtbbkhGPxg3aa8n2kfKZ9N6Q7DqrwIDAQAB
AoGBAJn5qu1D1FxE24Vxl7ZGPzdMigN227+NaPptak9CSR++gLm2KL+JBpcXt5XF
+20WCRvnWjl2QijPSpB5s6pWdHezEa1cl6WrqB1jDJd1U99WNCL5+nfEVD9IF+uE
ig0pnj+wAT5fu78Z0UjxD9307f9S7BLC8ou3dWVkIqob6W95AkEAuPGTNlTkquu/
wBJTb4/+/2ZCf7Ci9qvsN3+RcrzFkKa3uTtBOa6Xk2R61zBkucUgY6cQHPbxhFLN
TVmXdbwxTQJBAP0wGenVOq4dCPdz3NhyghkKT6SL2w/SgbrROiJ1mG9MoBq58/0g
k85I91R7nuvOYTKTUkhWdPYITpDarmPJzesCQGRBmOMgHCHH0NfHV3Gn5rz+61eb
IoyD4Hapceh4CsWCiyAfzhj9229sTecvdbr68Lb0zphVCdIIrQCca63IShUCQGYI
e3jzmHlQdCudArQruWgz8pKiVf7TW7qY1O/MKkk4PRFoPP6WoVoxp5LhWtM20Y7b
Nf628N2xzU+tAThvvE8CQQCI1C7GO3I5EMfqPbTSq2oZq8thvGlyFyI7SNNuvAHj
hj2+0217B9CcTZqloYln01CNDVuaoUgEvFSw1OdRB1tC
-----END RSA PRIVATE KEY-----
 
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC26X6A0WCWiVxdxq3jtm42yDdG
bf+99v2zyi0UMVGZfowlnkcWeMvpz8NBm2UVlrjZpnFr8wFkdHyjFFkq/ilclH3A
N4+Xw8Ap7CGJ2jVMyS5h9RRBUyf3F4D5Og8789Ywh9HXYyvD/6J62EtbbkhGPxg3
aa8n2kfKZ9N6Q7DqrwIDAQAB
-----END PUBLIC KEY-----

加密与解密

通常通信的时候,发送者使用接受者的公钥加密,接受者使用接受者私钥解密。

简而言之,Server给Client通信,需要加密内容,那么Client会生成一个秘钥对,Client的公钥client-public.pem和私钥client-private.pem 。Client把公钥公开给发送者,任何人都可以用来加密,然后Server使用client-public.pem进行加密,然后把内容发给Client,Client再使用私钥client-private.pem进行解密。

1.加密(encrypt)

# Server使用Client的公钥对内容进行rsa 加密
 
message = "hello client, this is a message"
with open("client-public.pem") as f:
  key = f.read()
  rsakey = RSA.importKey(key)
  cipher = Cipher_pkcs1_v1_5.new(rsakey)
  cipher_text = base64.b64encode(cipher.encrypt(message.encode('utf-8')))
  print(cipher_text.decode('utf-8'))
 
#加密结果:
HYQPGB+axWCbPp7PPGNTJEAhVPW0TX5ftvUN2v40ChBLB1pS+PVM3YGT5vfcsvmPZhW8NKVSBp8FwjLUnMn6yXP1O36NaunUzyHwI+cpjlkTwZs3DfCY/32EzeuKuJABin1FHBYUMTOKtHy+eEDOuaJTnZTC7ZBkdha+J88HXSc=

cipher_text 即 Master加密后将要发送给Client的密文。

2.解密(decrypt)

# Client使用自己的私钥对内容进行rsa 解密
 
with open("client-private.pem") as f:
  key = f.read()
  rsakey = RSA.importKey(key)
  cipher = Cipher_pkcs1_v1_5.new(rsakey)
  text = cipher.decrypt(base64.b64decode(encrypt_text), random_generator)
  print(text.decode('utf-8'))
 
#解密结果:
hello client, this is a message

这样Client就能看到Server所发的内容了,当然,如果Client想要给Server发消息,就需要Server先把其的公钥给Client,后者再使用公钥加密,然后发送给Server,最后Server使用自己的私钥解密。

签名与验签

当然,对于窃听者,有时候也可以对伪造Server给Client发送内容。为此出现了数字签名。也就是Server给Client发送消息的时候,先对消息进行签名,表明自己的身份,并且这个签名无法伪造。具体过程即Server使用自己的私钥对内容签名,然后Client使用Server的公钥进行验签。

签名

# Server使用自己的私钥对内容进行签名
 with open("server-private.pem") as f:
  key = f.read()
  rsakey = RSA.importKey(key)
  signer = Signature_pkcs1_v1_5.new(rsakey)
  digest = SHA.new()
  digest.update(message)
  sign = signer.sign(digest)
  signature = base64.b64encode(sign)
  print signature
 
#签名结果:
jVUcAYfgF5Pwlpgrct3IlCX7KezWqNI5tD5OIFTrfCOQgfyCrOkN+/gRLsMiSDOHhFPj2LnfY4Cr5u4eG2IiH8+uSF5z4gUX48AqCQlqiOTLk2EGvyp+w+iYo2Bso1MUi424Ebkx7SnuJwLiPqNzIBLfEZLA3ov69aDArh6hQiw=

验签

#Client使用Server的公钥对内容进行验签
 
with open("server-public.pem") as f:
  key = f.read()
  rsakey = RSA.importKey(key)
  verifier = Signature_pkcs1_v1_5.new(rsakey)
  digest = SHA.new()
  # Assumes the data is base64 encoded to begin with
  digest.update(message)
  is_verify = signer.verify(digest, base64.b64decode(signature))
  print is_verify
#验签结果:
True

总结

Pycrypto提供了比较完善的加密算法。RSA广泛用于加密与解密,还有数字签名通信领域。使用Publick/Private秘钥算法中,加密主要用对方的公钥,解密用自己的私钥。签名用自己的私钥,验签用对方的公钥。

  • 加密解密:公钥加密,私钥解密
  • 签名验签:私钥签名,公钥验签

无论是加密解密还是签名验签都使用同一对秘钥对。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
pyside写ui界面入门示例
Jan 22 Python
python 排序算法总结及实例详解
Sep 28 Python
python 写入csv乱码问题解决方法
Oct 23 Python
Python利用递归和walk()遍历目录文件的方法示例
Jul 14 Python
Pandas 同元素多列去重的实例
Jul 03 Python
python批量从es取数据的方法(文档数超过10000)
Dec 27 Python
python创建ArcGIS shape文件的实现
Dec 06 Python
已安装tensorflow-gpu,但keras无法使用GPU加速的解决
Feb 07 Python
python实现扫雷小游戏
Apr 24 Python
如何利用python web框架做文件流下载的实现示例
Jun 02 Python
python cv2.resize函数high和width注意事项说明
Jul 05 Python
python 通过pip freeze、dowload打离线包及自动安装的过程详解(适用于保密的离线环境
Dec 14 Python
wxpython绘制圆角窗体
Nov 18 #Python
wxpython绘制音频效果
Nov 18 #Python
python导入不同目录下的自定义模块过程解析
Nov 18 #Python
解决django model修改添加字段报错的问题
Nov 18 #Python
python sorted方法和列表使用解析
Nov 18 #Python
在Django中实现添加user到group并查看
Nov 18 #Python
Django继承自带user表并重写的例子
Nov 18 #Python
You might like
fleaphp crud操作之findByField函数的使用方法
2011/04/23 PHP
php获取本周星期一具体日期的方法
2015/04/20 PHP
Laravel框架控制器的request与response用法示例
2019/09/30 PHP
ExtJS 2.0实用简明教程 之Ext类库简介
2009/04/29 Javascript
来自国外的页面JavaScript文件优化
2010/12/08 Javascript
由Javascript实现的页面日历
2011/11/04 Javascript
javascript避免数字计算精度误差的方法详解
2014/03/05 Javascript
js实现图片在未加载完成前显示加载中字样
2014/09/03 Javascript
Jquery实现仿腾讯娱乐频道焦点图(幻灯片)特效
2015/03/06 Javascript
jquery自定义插件开发之window的实现过程
2016/05/06 Javascript
JQuery 传送中文乱码问题的简单解决办法
2016/05/24 Javascript
vue.js 左侧二级菜单显示与隐藏切换的实例代码
2017/05/23 Javascript
详解vue-cli 构建Vue项目遇到的坑
2017/08/30 Javascript
nodejs创建简易web服务器与文件读写的实例
2017/09/07 NodeJs
使用Vue自定义数字键盘组件(体验度极好)
2017/12/19 Javascript
webpack4 升级迁移的实现
2018/09/12 Javascript
小程序click-scroll组件设计
2019/06/18 Javascript
Vue vm.$attrs使用场景详解
2020/03/08 Javascript
vue中的.$mount('#app')手动挂载操作
2020/09/02 Javascript
Python实现抓取网页并且解析的实例
2014/09/20 Python
自己使用总结Python程序代码片段
2015/06/02 Python
Django 如何获取前端发送的头文件详解(推荐)
2017/08/15 Python
Python使用matplotlib绘图无法显示中文问题的解决方法
2018/03/14 Python
浅谈python中对于json写入txt文件的编码问题
2018/06/07 Python
Python实现的企业粉丝抽奖功能示例
2019/07/26 Python
pygame实现俄罗斯方块游戏(基础篇2)
2019/10/29 Python
python环境搭建和pycharm的安装配置及汉化详细教程(零基础小白版)
2020/08/19 Python
Django 实现图片上传和下载功能
2020/12/31 Python
CSS3制作ajax loader icon实现思路及代码
2013/08/25 HTML / CSS
校园安全广播稿
2014/02/08 职场文书
模范教师事迹材料
2014/02/10 职场文书
学习考察心得体会
2014/09/04 职场文书
个人租房协议书(范本)
2014/10/14 职场文书
12.4全国法制宣传日活动方案
2014/11/02 职场文书
毕业生捐书活动倡议书
2015/04/27 职场文书
工作态度怎么写
2015/06/25 职场文书