常见加密算法的Python实现

Python爬虫与数据挖掘

共 7304字,需浏览 15分钟

 ·

2021-11-16 06:06

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

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

移舟泊烟渚,日暮客愁新。
生活在信息化高度发展的时代,人们对信息安全和保密的意识也不断提高,在网络数据传输过程中往往需要对敏感数据进行加密处理,以保证数据的安全性。
本文主要介绍Base64、MD5,SHA-1,HMAC,DES/AES,RSA这几种加密算法和python实现代码示例。常用的加密方法基本都有对应的Python库,只需调用具体方法使用即可。


Base64位加密


最简单的加密方式,无密钥,只要拿到密文,就可以直接解密,一般情况下不单独使用,可以和其他加密方式混合使用,作为一层外部包装。

import base64

# 要加密的字符串
str_encrypt = 'hello!'
# 加密方法
# 转化为byte类型
base64_encrypt = base64.b64encode(str_encrypt.encode())
# 将字节串转为字符串
base64_encrypt_str = base64_encrypt.decode()

print("BASE64加密串:", base64_encrypt_str, type(base64_encrypt_str))

#解密方法
# 字符串转为字节串
base64_decrypt = base64_encrypt_str.encode()
# 得到加密的字符串
str_decrypt = base64.b64decode(base64_decrypt).decode()
print("BASE64解密串:", str_decrypt, type(str_decrypt))

BASE64加密串: aGVsbG/vvIE=  

BASE64解密串: hello!


MD5加密


MD5 信息-摘要算法(MD5 Message-Digest Algorithm),具有很高的安全性,可以产生出一个128位(16字节)的散列值(hash value),它对应任何字符串都可以加密成一段唯一的固定长度的代码,用于确保信息传输完整一致。目前MD5加密算法是不可逆的,当然这种方式加密的密文也不需要解密,需要的时候直接发送原始密文就好。

Python代码:
import hashlib

str_encrypt = "hello!"
# 对要加密的字符串进行加密
hash = hashlib.md5(str_encrypt.encode())
hash.update(str_encrypt.encode("utf8"))
value = hash.digest()
# 二进制
print("二进制的字符串", repr(value))

# 十六进制
print("十六进制的字符串", hash.hexdigest())
二进制的字符串:b'%\xe2\n\x04\x86\xa7\xf4\xc5Y@\xfa\xc7\xd6\xdc\t_'
十六进制的字符串:25e20a0486a7f4c55940fac7d6dc095f


SHA1加密


安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA),SHA1基于MD5,SHA1比MD5的安全性更强。对于长度小于2^ 64位的消息,SHA1会产生一个160位的报文摘要。

通过散列算法可实现数字签名实现,数字签名的原理是将要传送的明文通过一种函数运算(Hash)转换成报文摘要,报文摘要加密后与明文一起传送给接受方,接受方将接受的明文产生新的报文摘要与发送方的发来报文摘要解密比较,如果不一致表示明文已被篡改。

Python代码:
import hashlib

str_encrypt = "hello!"

# 对要加密的字符串进行加密
hash = hashlib.sha1(str_encrypt.encode())
hash.update(str_encrypt.encode("utf8"))
value = hash.hexdigest()

# 十六进制
print("十六进制的字符串",value)

十六进制的字符串 b8b92f40e0c5df69dcf5cdc1e327e1f87188aeb9



HMAC加密


散列信息鉴别码(Hash Message Authentication Code), HMAC加密算法是一种安全的基于加密hash函数和共享密钥的消息认证协议。

实现原理是用公开函数和密钥产生一个固定长度的值作为认证标识,用这个标识鉴别消息的完整性。

Python代码:
import hmac
import hashlib

str_encrypt = "hello!"
key="abc"
# 第一个参数是密钥key,第二个参数是待加密的字符串,第三个参数是hash函数

mac = hmac.new(key.encode(encoding="utf-8"),str_encrypt.encode("utf8"),hashlib.md5)

value=mac.hexdigest()  # 加密后字符串的十六进制格式

# 十六进制
print("十六进制的字符串",value)

十六进制的字符串 221479c27474cdf1ee245ffef26cfeee



DES加密


数据加密标准(Data Encryption Standard),属于对称加密算法。是一种使用密钥加密的块算法。接口参数有三个:Key、Data、Mode,Key为工作密Data为8个字节64位,是要被加密或被解密的数据;Mode工作方式:加密或解密。

Python代码:
import binascii
from pyDes import des, CBC, PAD_PKCS5
# 需要安装 pip install pyDes

#加密过程
def des_encrypt(secret_key,s):
    iv = secret_key
    k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
    en = k.encrypt(s, padmode=PAD_PKCS5)
    return binascii.b2a_hex(en)

#解密过程
def des_decrypt(secret_key, s):
    iv = secret_key
    k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
    de = k.decrypt(binascii.a2b_hex(s), padmode=PAD_PKCS5)
    return de

secret_str = des_encrypt('12345678''hello!')
print(secret_str)

clear_str = des_decrypt('12345678', secret_str)
print(clear_str)

b'7c48af7e37ecd280' 

b'hello!'


AES加密


高级加密标准(Advanced Encryption Standard),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。对加密快和密钥的字节数都有一定的要求,AES密钥长度的最少支持为128、192、256,加密块分组长度128位。需要知道密钥才能解密
使用命令pip3 install pycryptodome,安装pycryptodome

分组密码加密中的四种模式有ECB、CBC、CFB、OFB。其中最常见的有ECB和CBC。


1、ECB模式

对明文分组,每组明文通过加密算法和密钥位运算得到密文,之后按照顺序将计算所得的密文连在一起即可,各段数据之间互不影响。


2、CBC模式(使用最多的模式)

CBC模式需要一个初始化向量iv(和密钥长度相等的字符串),一般通过密钥生成器获取。


加密步骤如下:

1)首先将数据分组得到D1D2…Dn

2)第一组数据D1与初始化向量iv位运算的结果进行加密得到第一组密文C1

3)第二组数据D2与第一组的加密结果C1位运算以后的结果进行加密,得到第二组密文C2

4)之后的数据以此类推,得到Cn

5)按顺序连为C1C2C3…Cn即为加密结果。

特点:

1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。每个密文块依赖于所有的信息块,明文消息中一个改变会影响所有密文块

2.发送方和接收方都需要知道初始化向量

3.加密过程是串行的,无法被并行化(在解密时,从两个邻接的密文块中即可得到一个平文块。因此,解密过程可以被并行化

4.解密时初始化向量必须相同


Python代码:

ECB加密模式
import base64
from Crypto.Cipher import AES

#ECB加密模式

import base64
from Crypto.Cipher import AES


#使用补0方法

# # 需要补位,补足为16的倍数
def add_to_16(s):
    while len(s) % 16 != 0:
        s += '\0'
    return str.encode(s)  # 返回bytes

# 密钥长度必须为16、24或32位,分别对应AES-128、AES-192和AES-256
key = 'abc4567890abc458'
# 待加密文本
text = 'hello'
# 初始化加密器
aes = AES.new(add_to_16(key), AES.MODE_ECB)
# 加密
encrypted_text = str(base64.encodebytes(aes.encrypt(add_to_16(text))), encoding='utf8').replace('\n''')
# 解密
decrypted_text = str(
    aes.decrypt(base64.decodebytes(bytes(encrypted_text, encoding='utf8'))).rstrip(b'\0').decode("utf8"))

print('加密值:', encrypted_text)
print('解密值:', decrypted_text)
加密值:p3i7p25Ypel2X2yrFG4rCQ==

解密值:hello


CBC加密模式(一)

#CBC加密模式
import base64
from Crypto.Cipher import AES
from urllib import parse

AES_SECRET_KEY = 'helloBrook2abcde'  # 此处16|24|32个字符
IV = 'helloBrook2abcde' 


# padding算法

BS = len(AES_SECRET_KEY)

# 填充方案
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)

# 解密时删除填充的值

unpad = lambda s: s[0:-ord(s[-1:])]

def cryptoEn(string, key, iv):

# param string: 原始数据
# param key: 密钥
# param iv: 向

    mode = AES.MODE_CBC

    cipher = AES.new(key.encode("utf8"),mode,iv.encode("utf8"))

    encrypted = cipher.encrypt(bytes(pad(string), encoding="utf8"))

    return base64.b64encode(encrypted).decode("utf-8")


#CBC模式的解密代码

def cryptoDe(destring, key, iv):

# param destring: 需要解密的数据
# param key: 密钥
# param iv: 向量

    mode = AES.MODE_CBC
    
    decode = base64.b64decode(destring)

    cipher = AES.new(key.encode("utf8"),mode,iv.encode("utf8"))

    decrypted = cipher.decrypt(decode)

    return unpad(decrypted).decode("utf-8")


secret_str = cryptoEn('hello', AES_SECRET_KEY,IV)
print(secret_str)

clear_str = cryptoDe(secret_str.encode("utf8"), AES_SECRET_KEY,IV)
print(clear_str)
sqlpZ0AdaRAOQRabchzltQ==

hello


CBC加密模式(二)

import base64
from Crypto.Cipher import AES
from urllib import parse

AES_SECRET_KEY = 'helloBrook2abcde'  # 此处16|24|32个字符
IV = 'helloBrook2abcde' 

# padding算法
BS = len(AES_SECRET_KEY)
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s: s[0:-ord(s[-1:])]


class AES_ENCRYPT(object):
    def __init__(self):
        self.key = AES_SECRET_KEY
        self.mode = AES.MODE_CBC

    # 加密函数
    def encrypt(self, text):
        cryptor = AES.new(self.key.encode("utf8"), self.mode, IV.encode("utf8"))
        self.ciphertext = cryptor.encrypt(bytes(pad(text), encoding="utf8"))
        # AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题,使用base64编码
        return base64.b64encode(self.ciphertext).decode("utf-8")

    # 解密函数
    def decrypt(self, text):
        decode = base64.b64decode(text)
        cryptor = AES.new(self.key.encode("utf8"), self.mode, IV.encode("utf8"))
        plain_text = cryptor.decrypt(decode)
        return unpad(plain_text).decode("utf-8")


if __name__ == '__main__':
    aes_encrypt = AES_ENCRYPT()
    text = "Python"
    e = aes_encrypt.encrypt(text)
    d = aes_encrypt.decrypt(e)
    print(text)
    print(e)
    print(d)

待加密字符串:Python
加密值:X09JC6IqnsDFp9b9C57cUA==
解密值:Python

如果字符串包含中文,先对文本转ascii,将支持中文加密

text = base64.b64encode(text.encode('utf-8')).decode('ascii')



RSA加密


Rivest-Shamir-Adleman,RSA加密算法是一种非对称加密算法。公钥加密,私钥解密,在公开密钥加密和电子商业中RSA被广泛使用。目前最重要的加密算法!
可参考:
https://www.jianshu.com/p/7a4645691c68

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

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

往期精彩文章推荐:

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

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

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

/今日留言主题/

随便说一两句吧~~

浏览 33
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报