Python加密技术之SHA、DES、AES、RSA、base64加密(第2节)


1、使用SHA加密

在上一节教程里面,已经介绍了Python标准库中的hashlib模块,为我们提供了MD5的哈希算法。Python中常见的哈希算法还包括SHA加密算法SHA全称安全哈希算法(英文名称:Secure Hash Algorithm),目前被广泛应用于密码散列、数字签名等领域,SHA加密算法通常包括五个算法,分别是SHA-1、SHA-256、SHA-224、SHA-384、SHA-512,其中SHA-256、SHA-224、SHA-384、SHA-512这四个算法有时并称为SHA-2加密算法。SHA加密算法是比MD5更安全一点的摘要算法,MD5的密文是32位,而SHA-1是40位,版本越强,密文越长,当然付出的代价是速度越慢。例如:

动手练一练:

import hashlib

# 原始数据
data = "学Python编程,进入www.pyhint.com在线学习"

# 创建哈希对象
sha1 = hashlib.sha1(data.encode())
sha256 = hashlib.sha256(data.encode())

# 获取哈希值
result1 = sha1.hexdigest()
result2 = sha256.hexdigest()

print(f"原始消息:{data}")
print(f"sha1哈希值:{result1}")
print(f"sha256哈希值:{result2}")

执行以上代码,输出结果为:

原始消息学Python编程进入www.pyhint.com在线学习
sha1哈希值100f60680f4b0d84b0c272573d003f9024bbbfa5
sha256哈希值604aed95eb77dd0d23d22b9163b818ff55f04b2c05ab3efa1ab82c54aa196a64

2、使用DES加密

DES加密全称数据加密标准(英文名称:Data Encryption Standard),是一种典型的对称加密算法,加密与解密使用同一密钥,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),DES是一个分组加密算法,使用一个56位的密钥以及附加的8位奇偶校验位,产生最大64位的分组大小。这是一个迭代的分组密码,使用称为Feistel的技术,其中将加密的文本块分成两半。使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES使用16个循环,使用异或,置换,代换,移位操作四种基本运算。

由于56位密钥长度相对较短,所以DES是不安全的,现在基本上已被更高级的加密标准AES取代。在Python中,我们可以使用pycryptodome库来实现DES加密解密算法。例如:

动手练一练:

from Crypto.Cipher import DES

def des_encrypt(key, plaintext):
    key = key.encode("utf-8")
    plaintext = plaintext.encode("utf-8")

    # 填充明文
    length = 8 - (len(plaintext) % 8)
    plaintext += bytes([length]) * length

    # 初始化加密器
    cipher = DES.new(key, DES.MODE_ECB)

    # 加密
    ciphertext = cipher.encrypt(plaintext)

    return ciphertext

def des_decrypt(key, ciphertext):
    key = key.encode("utf-8")

    # 初始化解密器
    cipher = DES.new(key, DES.MODE_ECB)

    # 解密
    plaintext = cipher.decrypt(ciphertext)

    # 去除填充
    plaintext = plaintext[:-plaintext[-1]]

    return plaintext.decode("utf-8")

# 密钥 8位或16位,必须为bytess
key = "12345abc"
plaintext = "学Python编程,进入www.pyhint.com在线学习"
ciphertext = des_encrypt(key, plaintext)
print("加密结果:", ciphertext)
plaintext = des_decrypt(key, ciphertext)
print("解密结果:", plaintext)

执行以上代码,输出结果为:

加密结果 b'\x03\x04\xb9\x03O\xa8p\x96\x818\xae\xbf\xe7\xac\xcfx\xc4\xe4\x04\xc9*\x14\x9b\x87\xcf\xf2V\xe8\xd2C\x1a!\xb7\t3I\x99\xe99\x9b\xdexf.`\x1a\x05\x10\xf4.jp6s\xbfX'
解密结果 学Python编程进入www.pyhint.com在线学习

虽然DES算法已经被认为不能满足现代密码学的安全要求,但在某些场景下仍被广泛使用。

3、使用AES加密

对称加密算法以其高效性在数据加密领域占据重要地位,其中AES加密算法是最为广泛应用的一种对称加密算法。AES全称高级加密标准(英文名称:Advanced Encryption Standard),在密码学中又称Rijndael加密法,由美国国家标准与技术研究院(NIST)于2001年11月26日发布,并在2002年5月26日成为有效的标准。这个标准用来替代原先的DES,已经成为一种被广泛使用的对称加密算法,适用于大量数据的加密,包括文件,它本身只有一个密钥,即用来实现加密,也用于解密。

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

动手练一练:

from Crypto.Cipher import AES
from Crypto import Random
from binascii import a2b_hex

# 要加密的内容
data = "学Python编程,进入www.pyhint.com在线学习"
# 密钥key必须为16、24或者32位长度
key = b"abcdefghijklmnop"
# 生成长度等于AES 块大小的不可重复的密钥向量
iv = Random.new().read(AES.block_size)
print(iv)
print("-------这是虚线-------")
# 使用key和iv初始化AES对象,使用MODE_CFB模式
result = AES.new(key, AES.MODE_CFB, iv)
# 加密的明文长度必须为16的倍数,如果长度不为16的倍数,则需要补足为16的倍数
# 将iv(密钥向量)加到加密的密钥开头,一起传输
text = iv + result.encrypt(data.encode())
# 解密的话需要用key和iv生成的AES对象
print(text)
print("-------这是虚线-------")
mydecrypt = AES.new(key, AES.MODE_CFB, text[:16])
# 使用新生成的AES对象, 将加密的密钥解密
decrytext = mydecrypt.decrypt(text[16:])
print("解密结果:", decrytext.decode())

执行以上代码,输出结果为:

b'\x1f\xa2\x85+\x0e\x00.\xa7\xb9[F\xada\x1a\xe1\xc8'
-------这是虚线-------
b'\x1f\xa2\x85+\x0e\x00.\xa7\xb9[F\xada\x1a\xe1\xc8n\xba\x05\xe0y3e\xe8\xda\x00\xa1\xc7\x84Czk\x08\xce7\xe8\x164^\xbc-\xb6\xf3\xce\xcc1x!d.\xcc\xe9\xfb\xff\x05*\xf5\xa9W\x01\x08\xc4m\x95vu'
-------这是虚线-------
解密结果 学Python编程进入www.pyhint.com在线学习

4、使用RSA加密

RSA加密算法是一种典型的非对称加密算法,RSA英文名称:Rivest-Shamir-Adleman,是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的,RSA就是他们三人姓氏开头字母拼在一起组成的。

RSA加密算法使用一对密钥来加密和解密数据。RSA算法包括密钥生成、加密、解密三个步骤。RSA算法在数据传输过程中广泛用于安全地加密敏感信息,例如在Web浏览器和服务器之间进行安全通信,数字签名,以及安全地交换对称加密密钥等方面。它是公认的安全可靠的加密算法之一,并且能够抵抗到目前为止已知的所有密码攻击。

RSA加密算法通常使用openssl或keytools等工具生成一对公私钥对,使用被公钥加密的数据可以使用私钥来解密,相反,被私钥加密的数据也可以被公钥解密。在实际使用中私钥一般保存在发布者手中,是私有的不对外公开的,只将公钥对外公布,就能实现只有私钥的持有者才能将数据解密的方法。 这种加密方式安全系数很高,因为它不用将解密的密钥进行传递,从而没有密钥在传递过程中被截获的风险,而破解密文几乎又是不可能的。例如:

动手练一练:

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import binascii

def generate_keys():
    # 生成长度为2048的秘钥
    key = RSA.generate(2048)
    # 生成公钥
    private_key = key.export_key()
    # 生成私钥
    public_key = key.publickey().export_key()
    return private_key, public_key

def encrypt_message(public_key, message):
    cipher = PKCS1_OAEP.new(RSA.import_key(public_key))
    # 使用公钥加密,得到密文(bytes对象)
    encrypted_message = cipher.encrypt(message.encode())
    # 一般会转成十六进制进行传输
    return binascii.hexlify(encrypted_message).decode()

def decrypt_message(private_key, encrypted_message):
    cipher = PKCS1_OAEP.new(RSA.import_key(private_key))
    # 解密
    decrypted_message = cipher.decrypt(
        binascii.unhexlify(encrypted_message)
    )
    return decrypted_message.decode()

# 分别生成公钥和私钥
private_key, public_key = generate_keys()
message = "学Python编程,进入www.pyhint.com在线学习"
# 使用公钥加密
encrypted = encrypt_message(public_key, message)
print("加密结果:", encrypted)
print("公钥长度:", len(encrypted))
# 使用私钥解密
decrypted = decrypt_message(private_key, encrypted)
print("解密结果:", decrypted)

执行以上代码,输出结果为:

加密结果 3d5d24c2b254a45a54610ca0f941fc61543bbe5bd7671e7e11a42947bf9eac69bdf2e3a5273b2b5317b091862aa6600597a6839229f2c81952d1ef8016b8b60a360175c901f0c20de7af541b526d6cecfdd89bec9584d3772fa5acbfc7dbc7af9cc77406cd3f589c31c57ca9323133c5d1d0964dd8c1feff2a84c86a25ceeb37fc7e3f4398ade83c3bf82a5ca07bb07ce2ca652d8104104da3cc6a8894e67e68ff8f49c2d86f80318b1849bc686c5a84198c321cb905c24e08414a189c8330ff58e793cd1a9200e84d75771d2c53045a6388e6ed19bb363b7934c05918870d17cce54957ba00adc4ac224baedb20b8fd17952fef171a55a7d8232972576551fb
公钥长度 512
解密结果 学Python编程进入www.pyhint.com在线学习

##5、使用Base64加密-(无密钥)

**Base64加密**是网络上最常见的用于传输8-bit字节码的编码方式之一**Base64**就是一种基于64个可打印字符来表示二进制数据的方法广泛应用于MIME协议作为电子邮件的传输编码生成的编码可逆后一两位可能有=”,生成的编码都是ascii字符它的优点是速度快ascii字符肉眼不可理解它的缺点是编码比较长非常容易被破解仅适用于加密非关键信息的场合

在网络应用领域常有人将Base64编码误称为加密实际上Base64只是一种将二进制数据转换为可打印字符的编码方式不具备加密特性它的主要应用是实现不同设备和平台间的二进制数据传输及特定协议和规范中的处理例如

动手练一练
```python
import base64

# 原始字符串
data = "学Python编程,进入www.pyhint.com在线学习"

# 对字符串进行Base64编码
a = base64.b64encode(data.encode('utf-8'))
print("Base64编码后的字符串:", a.decode('utf-8'))

# 对Base64编码的字符串进行解码
b = base64.b64decode(a)
print("Base64解码后的字符串:", b.decode('utf-8'))

执行以上代码,输出结果为:

Base64编码后的字符串: 5a2mUHl0aG9u57yW56iL77yM6L+b5YWld3d3LnB5aGludC5jb23lnKjnur/lrabkuaA=
Base64解码后的字符串: 学Python编程进入www.pyhint.com在线学习

上面的例子中,首先将原始字符串转换为UTF-8编码的字节串,然后使用b64encode进行编码,得到的是字节串,因此需要解码为字符串。解码过程中使用b64decode函数,它接受字节串作为参数,返回原始数据的字节串。最后,将解码的字节串解码为字符串输出。