Python 常见加密方式和实现

Python 加密与解密小结

这篇文章主要介绍了Python 加密与解密,使用base64或pycrypto模块

前言

据记载,公元前400年,古希腊人发明了置换密码。1881年世界上的第一个电话保密专利出现。在第二次世界大战期间,德国军方启用“恩尼格玛”密码机,密码学在战争中起着非常重要的作用。随着信息化和数字化社会的发展,人们对信息安全和保密的重要性认识不断提高,于是在1997年,美国国家标准局公布实施了“美国数据加密标准(DES)”,民间力量开始全面介入密码学的研究和应用中,采用的加密算法有DES、RSA、SHA等。随着对加密强度需求的不断提高,近期又出现了AES、ECC等。

使用密码学可以达到以下目的:保密性:防止用户的标识或数据被读取。数据完整性:防止数据被更改。身份验证:确保数据发自特定的一方。

我们所说的加密方式,都是对二进制编码的格式进行加密的,对应到Python中,则是我们的Bytes。所以当我们在Python中进行加密操作的时候,要确保我们操作的是Bytes,否则就会报错。注:两位十六进制常常用来显示一个二进制字节。

将字符串和Bytes互相转换可以使用encode()decode()方法。

# 方法中不传参数则是以默认的utf-8编码进行转换
In [1]: '南北'.encode()
Out[1]: b'\xe5\x8d\x97\xe5\x8c\x97'In [2]: b'\xe5\x8d\x97\xe5\x8c\x97'.decode()
Out[2]: '南北'

利用binascii模块可以将十六进制显示的字节转换成我们在加解密中更常用的显示方式:

In [1]: import binasciiIn [2]: '南北'.encode()
Out[2]: b'\xe5\x8d\x97\xe5\x8c\x97'In [3]: binascii.b2a_hex('南北'.encode())
Out[3]: b'e58d97e58c97'In [4]: binascii.a2b_hex(b'e58d97e58c97')
Out[4]: b'\xe5\x8d\x97\xe5\x8c\x97'In [5]: binascii.a2b_hex(b'e58d97e58c97').decode()
Out[5]: '南北'

加密算法分类

对称加密算法:

对称加密采用了对称密码编码技术,它的特点是文件加密和解密使用相同的密钥发送方和接收方需要持有同一把密钥,发送消息和接收消息均使用该密钥。相对于非对称加密,对称加密具有更高的加解密速度,但双方都需要事先知道密钥,密钥在传输过程中可能会被窃取,因此安全性没有非对称加密高。常见的对称加密算法:DES,AES,3DES等等

非对称加密算法:

文件加密需要公开密钥(publickey)和私有密钥(privatekey)。接收方在发送消息前需要事先生成公钥和私钥,然后将公钥发送给发送方。发送放收到公钥后,将待发送数据用公钥加密,发送给接收方。接收到收到数据后,用私钥解密。在这个过程中,公钥负责加密,私钥负责解密,数据在传输过程中即使被截获,攻击者由于没有私钥,因此也无法破解。非对称加密算法的加解密速度低于对称加密算法,但是安全性更高。非对称加密算法:RSA、DSA、ECC等算法

消息摘要算法:

消息摘要算法可以验证信息是否被篡改。在数据发送前,首先使用消息摘要算法生成该数据的签名,然后签名和数据一同发送给接收者。接收者收到数据后,对收到的数据采用消息摘要算法获得签名,最后比较签名是否一致,以此来判断数据在传输过程中是否发生修改。

Python加密库

PyCrypto是 Python 中密码学方面最有名的第三方软件包。可惜的是,它的开发工作于2012年就已停止。其他人还在继续发布最新版本的 PyCrypto,如果你不介意使用第三方的二进制包,仍可以取得Python 3.5 的相应版本。比如,可以在 Github 上找到了对应Python3.5的PyCrypto 二进制包。幸运的是,有一个该项目的分支 PyCrytodome 取代了 PyCrypto 。

# Linux 上安装它,你可以使用以下pip 命令:
pip3 install -i https://pypi.douban.com/simple pycryptodome
# 导入
import Crypto# 在Windows 系统上安装则稍有不同:
pip3 install -i https://pypi.douban.com/simple pycryptodomex
# 导入
import Cryptodome

DES加密

全称为Data EncryptionStandard,即数据加密标准,是一种使用密钥加密的块算法,又被称为美国数据加密标准

DES算法的入口参数有三个:Key、Data、Mode。其中Key为7个字节共56位,是DES算法的工作密钥;Data为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密。

密钥长64位,密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位,使得每个密钥都有奇数个1),分组后的明文组和56位的密钥按位替代或交换的方法形成密文组。

from Crypto.Cipher import DES
key = b'abcdefgh' # 密钥 8位或16位,必须为bytesdef pad(text):# 加密函数,如果text不是8的倍数【加密文本text必须为8的倍数!】,那就补足为8的倍数while len(text) % 8 != 0:text += ' 'return textdes = DES.new(key, DES.MODE_ECB)  # 创建一个DES实例
text = 'Python rocks!'
padded_text = pad(text)  # 需要加密的数据
encrypted_text = des.encrypt(padded_text.encode('utf-8'))  # 加密
print(encrypted_text)
# rstrip(' ')返回从字符串末尾删除所有字符串的字符串(默认空白字符)的副本
plain_text = des.decrypt(encrypted_text).decode().rstrip(' ')  # 解密
print(plain_text)

3DES

3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。

由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解。3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。

3DES(即Triple DES)是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准),加密算法,其具体实现如下:设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,M代表明文,C代表密文,这样:

3DES加密过程为:C=Ek3(Dk2(Ek1(M)))

3DES解密过程为:M=Dk1(EK2(Dk3(C)))

AES加密

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。

AES在软件及硬件上都能快速地加解密,相对来说较易于实作,且只需要很少的存储器。作为一个新的加密标准,目前正被部署应用到更广大的范围。

AES只是个基本算法,实现AES有若干模式。其中的CBC模式因为其安全性而被TLS(就是https的加密标准)和IPSec(win采用的)作为技术标准。简单地说,CBC使用密码和salt(起扰乱作用)按固定算法(md5)产生key和iv。然后用key和iv(初始向量,加密第一块明文)加密(明文)和解密(密文)。

特点

  1. 抵抗所有已知的攻击。
  2. 在多个平台上速度快,编码紧凑。
  3. 设计简单。

AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。密钥的长度可以使用128位、192位或256位(16、24和32字节)。密钥的长度不同,推荐加密轮数也不同。

##################################### AES.MODE_ECB ####################################
from Cryptodome.Cipher import AES
from binascii import b2a_hex, a2b_hex
# 密钥key 长度必须为16(AES-128)、24(AES-192)、或32(AES-256)Bytes 长度.
# 目前AES-128足够用
key = 'abcdefghigklmnop'
# 加密内容需要长达16位字符,所以进行空格拼接
def pad(text):while len(text) % 16 != 0:text += ' 'return text# 进行加密算法,模式ECB模式,把叠加完16位的秘钥传进来
aes = AES.new(key.encode(), AES.MODE_ECB)
# 加密内容,此处需要将字符串转为字节
text = 'hello'
# 进行内容拼接16位字符后传入加密类中,结果为字节类型
encrypted_text = aes.encrypt(pad(text).encode())
encrypted_text_hex = b2a_hex(encrypted_text)
print(encrypted_text_hex)# 此处是为了验证是否能将字节转为字符串后,进行解密成功
# 实际上a 就是 encrypted_text ,也就是加密后的内容
# 用aes对象进行解密,将字节类型转为str类型,错误编码忽略不计
de = str(aes.decrypt(a2b_hex(encrypted_text_hex)), encoding='utf-8',errors="ignore")
# 获取str从0开始到文本内容的字符串长度。
print(de[:len(text)])##################################### AES.MODE_CFB ####################################
from Cryptodome.Cipher import AES
from Cryptodome import Random
from binascii import b2a_hex  # 要加密的明文
data = '南来北往'
# 密钥key 长度必须为16(AES-128)、24(AES-192)、或32(AES-256)Bytes 长度.
# 目前AES-128足够用
key = b'this is a 16 key'
# 生成长度等于AES块大小的不可重复的密钥向量
iv = Random.new().read(AES.block_size)# 使用key和iv初始化AES对象, 使用MODE_CFB模式
mycipher = AES.new(key, AES.MODE_CFB, iv)
# 加密的明文长度必须为16的倍数,如果长度不为16的倍数,则需要补足为16的倍数
# 将iv(密钥向量)加到加密的密文开头,一起传输
ciphertext = iv + mycipher.encrypt(data.encode())# 解密的话要用key和iv生成新的AES对象
mydecrypt = AES.new(key, AES.MODE_CFB, ciphertext[:16])
# 使用新生成的AES对象,将加密的密文解密
decrypttext = mydecrypt.decrypt(ciphertext[16:])print('密钥k为:', key)
print('iv为:', b2a_hex(ciphertext)[:16])
print('加密后数据为:', b2a_hex(ciphertext)[16:])
print('解密后数据为:', decrypttext.decode())

面向对象方式

#coding: utf8
import sys
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hexclass prpcrypt():def __init__(self, key):self.key = keyself.mode = AES.MODE_CBC#加密函数,如果text不是16的倍数【加密文本text必须为16的倍数!】,那就补足为16的倍数def encrypt(self, text):cryptor = AES.new(self.key, self.mode, self.key)#这里密钥key 长度必须为16(AES-128)、24(AES-192)、或32(AES-256)Bytes 长度.目前AES-128足够用length = 16count = len(text)add = length - (count % length)text = text + ('\0' * add)self.ciphertext = cryptor.encrypt(text)#因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题#所以这里统一把加密后的字符串转化为16进制字符串return b2a_hex(self.ciphertext)#解密后,去掉补足的空格用strip() 去掉def decrypt(self, text):cryptor = AES.new(self.key, self.mode, self.key)plain_text = cryptor.decrypt(a2b_hex(text))return plain_text.rstrip('\0')if __name__ == '__main__':pc = prpcrypt('keyskeyskeyskeys')   #初始化密钥e = pc.encrypt("00000")d = pc.decrypt(e)           print e, de = pc.encrypt("00000000000000000000000000")d = pc.decrypt(e)         print e, d

运行结果

a9755fd70d8d6db65a6fac12d4797dde 00000

2c1969f213c703ebedc36f9e7e5a2b88922ac938c983201c200da51073d00b2c 00000000000000000000000000

RSA加密

RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。

该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。

3个参数:rsa_n, rsa_e,message。rsa_n, rsa_e 用于生成公钥,message: 需要加密的消息

因为RSA加密算法的特性,RSA的公钥私钥都是10进制的,但公钥的值常常保存为16进制的格式,所以需要将其用int()方法转换为10进制格式。

安装 pip install rsa

使用

import rsa
from binascii import b2a_hex, a2b_hexclass rsacrypt():def __init__(self, pubkey, prikey):self.pubkey = pubkeyself.prikey = prikeydef encrypt(self, text):self.ciphertext = rsa.encrypt(text.encode(), self.pubkey)# 因为rsa加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题# 所以这里统一把加密后的字符串转化为16进制字符串return b2a_hex(self.ciphertext)def decrypt(self, text):decrypt_text = rsa.decrypt(a2b_hex(text), prikey)return decrypt_textif __name__ == '__main__':pubkey, prikey = rsa.newkeys(256)rs_obj = rsacrypt(pubkey,prikey)text='hello'ency_text = rs_obj.encrypt(text)print(ency_text)print(rs_obj.decrypt(ency_text))"""
b'7cb319c67853067abcd16aad25b3a8658e521f83b1e6a6cf0c4c2e9303ad3e14'
b'hello'
"""

base64

 

Base64编码,64指A-Z、a-z、0-9、+和/这64个字符,还有“=”号不属于编码字符,而是填充字符。为什么发明这么个编码呢,这个编码的原理很简单,“破解”也很容易,原因是电子邮件刚出来的时候,只传递英文字符,这没有问题,但是后来,中国人,日本人都要发email,这样问题就来了,因为这些字符有可能会被邮件服务器或者网关当成命令处理,故必须得有一种编码来对邮件进行加密,但是加密的目的是为了能够使得一些原始的服务器不出问题(现在服务器早已经能处理这些乱七八糟得情况了,不过因为已经形成了一套规范,所以邮件还是得经过Base64编码才能传递)。

优点:方法简单。缺点:不保险,别人拿到密文可以自己解密出明文

编码原理:将3个字节转换成4个字节((3 X 8)=24=(4X6)),先读入3个字节,每读一个字节,左移8位,再右移四次,每次6位,这样就有4个字节了。解码原理:将4个字节转换成3个字节,先读入4个6位(用或运算),每次左移6位,再右移3次,每次8位,这样就还原了。

import base64
s1 = base64.encodestring('hello world')
s2 = base64.decodestring(s1)
print s1, s2

结果

aGVsbG8gd29ybGQ=
hello world

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/454665.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jenkins日志乱码linux,Jenkins控制台中乱码问题解决

由于服务器环境及应用层各版本的不同、编码方式的不同因此会有很多种情况会出现乱码问题。由于Jenkins中的job运行的是独立的一个shell环境,许多的环境变量与服务器中是不一样的,因此在job中执行的命令也就会有所差异。因此可以在job中执行env命令&#…

13,反转链表《剑指offer》

题目: 输入一个链表,反转链表后,输出链表的所有元素。 思路: 反转链表,对于片段 1--->2--->3循环操作; 要反转链表需要两步: 一,将2->next指向1 (如果不保存3那…

什么是面试的关键?资深HR告诉你!

求职指南、面试宝典、应聘手册……到任何一个书店去转转,总能发现一两本这样的书,有关面试应聘的包装技巧实在太多,既让应聘者眼花缭乱、无所适从,也让人事经理头疼,总担心会被应聘者的包装所蒙骗。东方控股集团有限公…

windows商店_Windows记事本应用现在可以从Microsoft Store中获得

早在2019年8月,微软就宣布将把人们最常用的Windows记事本应用搬到应用商店,让这款深受用户喜爱的应用更新速度更快、响应更灵敏。12月晚些时候,微软却放弃了这一计划,也没有给出太多理由。但现在,这一计划已经完成&…

.net core linux 编译,.NET Core 源码编译的问题解析

引言: .NET Core 源码编译https://github.com/dotnetgit clone https://github.com/dotnet/runtime.git一:Windows 编译VS 2019 16.6(不要安装预览版)Win 10 专业版,最新版本 (1903/2004)长路径支持:组策略(gpedit.msc) > 计算…

jmeter 压测duobbo接口,施压客户端自己把自己压死了

jmeter 压测duobbo接口,jmeter代码不合理,导致每执行一次请求,会调用一次消耗内存的实例化。导致越压越慢,请求发不出去。这个时候需要考虑修改代码了。 截图中,tps越来越少。 原来初始化的代码放在 runTest中执行。修…

oracle pl/sql 包

包用于在逻辑上组合过程和函数,它由包规范和包体两部分组成。1)、我们可以使用create package命令来创建包,如:i、创建一个包sp_packageii、声明该包有一个过程update_saliii、声明该包有一个函数annual_income --声明该包有一个存储过程和一…

MySQL 之 explain

explain 介绍 explain显示了MySQL如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。简单讲,它的作用就是分析查询性能。explain 查询SQL - 用于显示SQL执行信息参数,根据参考信息可以进行SQL优化 示例&#x…

[置顶]微软面试智力题

这个笑话反映了两个公司不同的企业文化。很多人都知道微软的企业文化是宽松和自由,给员工一个充分发挥创造力的空间,这也是微软能吸引很多人才的原因之一。但是,要想进微软工作可不容易,微软在招聘工作上一点也不马虎,…

背单词软件 单词风暴 分享id_周一考研高效背单词系列(一):利用单词软件如何背好单词...

高效背单词考研单词作为考研路上的第一大难关,相信很多小伙伴都在这上面吃过不少苦,有同学更是看到密密麻麻的大纲词汇就头疼,但只要是学习就是有方法的,今天,我们开始推出高效背单词系列——墨墨背单词。另&#xff1…

linux c++ 编译 库,LINUX C/C++ 编译库关系

在LINUX 下安装个啥,都要涉及到编译,尤其是开源软件. 那么编译就涉及到C/C 和对应的库. 我们理一理之间的关系有助于MYSQL8源码编译libc glibc libc libstdc eglibc GCC G CMakeGDB从libc说起。libc是Linux下原来的标准C库,也就是当初写hello world时包含的头文件#…

Linux_学习_Day3_bash

Shell bash是外部程序:type/whichis bash。 shell, 子shell。可以利用bash打开另一个bash。即打开一个子shell。并且每个进程是独立存在的。对于子shell而言,bash并不认知其他bash的存在。 执行了多次bash,要退出只需exit。用pst…

mysql 之 优化 (收集于网络)

(以下内容均来自于网络,如果有版权限制,请联系我0.0) Mysql存储千亿级的数据,是一项非常大的挑战。Mysql单表可以存储10亿级的数据,只是这个时候性能非常差,项目中大量的实验证明,M…

hadoop-09-安装资源上传

hadoop-09-安装资源上传 在/software/www/html 下面上传 ambari HDP HDP-UTILS-1.1.0.21 文件,之后解压;

easyui 收费_收费班长喻玉华三尺岗亭献青春

- 2020 第四期 人物访谈报道 -拼搏人生最美励志先锋人物专访2013年,22岁的她来到巴南高速这个大家庭中,成为恩阳收费站一名普通的收费员。怀着对事业的执着追求与热爱,经过两年不懈的努力,获得了领导和同事的认可和喜爱。2015年5月…

编程技术面试的五大要点

(写在前面的话:本文最初发表于《程序员》杂志2011年10月刊,并收录到《剑指Offer——名企面试官精讲典型编程题》一书中。) 近年来找工作一直是一个很热门的话题。我们要想找到心仪的工作,难免需要经过很多轮面试。编程…

访问linux服务主机,如何把Linux配置为日志服务主机。

如网络设备很多,可把同类的设备配置为相同的设备号例:more switch.log | grep X.X.X.X //查看某一设备的日志审核和记录系统的事件是非常重要的。如果仅仅把系统事件作为日志记录下来,而不去查看,还是无济于事。可用webadmin管理和…

WSARecv() 函数使用解析

详情参考:https://msdn.microsoft.com/en-us/library/windows/desktop/ms741688(vvs.85).aspx 简述 The WSARecv function receives data from a connected socket or a bound connectionless socket. The WSARecv function provides some additional features comp…

获取 docker 容器(container)的 ip 地址

获取单个IP docker inspect --format {{ .NetworkSettings.IPAddress }} <container-ID> 获取所有容器IP docker inspect -f {{.Name}} - {{.NetworkSettings.IPAddress }} $(docker ps -aq)转载于:https://www.cnblogs.com/Tempted/p/7774789.html

山西台达plc可编程控制器_可编程控制器2(PLC)控制原理

采用继电器控制采用PC控制PC的控制原理(继电器PC控制)a)当SB1按下&#xff0c;输入继电器00000的线圈通电&#xff0c;00000的常开触点闭合&#xff0c;使得输出继电器01000的线圈得电&#xff0c;01000对应的硬输出触电闭合&#xff0c;KM1得电M1开始运转&#xff0c;同时0100…