✨前言
cryptography 库是一个强大的 Python 加密库,提供了对加密算法和协议的高层和低层访问。它是用来实现数据加密、签名、密钥管理等功能的。以下是一些常见用法的详解,帮助你理解如何使用这个库。
✨安装
首先,你需要确保安装了 cryptography 库:
pip install cryptography
✨1. 对称加密
对称加密是指加密和解密使用相同的密钥。Fernet 是 cryptography 库中提供的对称加密类。
示例:使用 Fernet 进行加密和解密
from cryptography.fernet import Fernet
# 生成密钥
key = Fernet.generate_key()
cipher_suite = Fernet(key)
# 加密数据
plain_text = b"Hello, World!"
cipher_text = cipher_suite.encrypt(plain_text)
print(f"Cipher Text: {cipher_text}")
# 解密数据
decrypted_text = cipher_suite.decrypt(cipher_text)
print(f"Decrypted Text: {decrypted_text.decode('utf-8')}")
"""
Cipher Text: b'gAAAAABm1SuaILy-UxWXz4hpBxVmrFlrZ1pPGJPTLZNMqqp38qwcHjTX16BbWasLUvhkCCL485jSfCTZ0HQWUptYniUX6EAwQA=='
Decrypted Text: Hello, World!
"""
✨2. 非对称加密
非对称加密使用一对密钥:公钥和私钥。cryptography 库中提供了 RSA 算法的实现。
示例:使用 RSA 进行加密和解密
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes
# 生成 RSA 密钥对
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
# 加密数据
message = b"Hello, RSA!"
cipher_text = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(f"Cipher Text: {cipher_text}")
# 解密数据
decrypted_text = private_key.decrypt(
cipher_text,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(f"Decrypted Text: {decrypted_text.decode('utf-8')}")
"""
Cipher Text: b';2\xdf\xc80%\x19\xf4\x95\xbc<\xfa\xb7\xe7\'\x94\xed!\xd0\x17\xdf\xb7c\xe3Q\xd6caEU\xc6 g(r\xa1-\xa1*y\xf9\xac\x1d"\xa7F\xd8J[w6Ly7\x06m5\xd2\x1d\xa9\x87A_\xb6\n\x078\xfb\xcc\x80\xf8\xad#\x86\x88\x97\xd8j\x17s\xf4\xc0\t\xc2\xb24i\x1c\x1c\xc1\x96\r\xac2\xd9\xaf\xfal\xa2n\xac\xb7\xa4C\xb6\xac\x1a,\xec\x94\xfa\x9b\xf2\xca\x030v#\x00\xdc\xd6\xa7\xf8:o\x1eK\xc3L\xf4\x88B\ru\xa1\x8b\xc0//@\x0c\x84\x047\xa7\xa1\x1f\x82\xe2\xdd\x0f\tT\x9df\xb5\x98n\xe2\xb8\x0e\x8c\xcb\x95T\x93SjX\xaf;97\xad\x19\x9el\x8d\xa3\xacr\xe0tT\x8c\x18\xa2!\x15\xd8\xf3\x8e\x88{\x01\x96[\xfa\xff\xc70\xef\xfe\xa5C\x01b?\xe7\xa9\xbdLw\xa8\x05^?\xbe\x94p\xa4#j\xeb\xef\xfb\xac\x92\xca|}`\xce\xe6\x7f&\xd2h\x19\x19K\x91\xde\xc5\xce\xdc\x91\xb7|\xaf\x9ef\x8d\xc8\xb7\xaf'
Decrypted Text: Hello, RSA!
"""
✨3. 数字签名
数字签名可以用来验证消息的完整性和来源。可以使用非对称加密的私钥进行签名,使用公钥进行验证。
示例:使用 RSA 进行数字签名
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
"""
代码解释:
生成密钥对:
使用 RSA 算法生成一个私钥和相应的公钥。这里的公钥和私钥都是 2048 位的。
签名消息:
用私钥对一条消息进行签名,使用 PSS 填充和 SHA-256 哈希算法。
验证签名:
使用公钥验证签名是否有效。若有效,则证明消息在签名前未被篡改。
"""
# 生成密钥对
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
# 获取公钥
public_key = private_key.public_key()
# 保存私钥
private_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
)
# 打印私钥
print("Private Key:")
print(private_pem.decode())
# 签名消息
message = b"Hello, this is a secret message."
signature = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
# 打印签名
print("Signature:")
print(signature.hex())
# 验证签名
try:
public_key.verify(
signature,
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("Signature is valid.")
except Exception as e:
print("Signature is invalid:", str(e))
"""
Private Key:
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAq3zlAQlVy/4/S+St69LJubb/OUfZLdI1L+ERXfwZOfro0sWU
DXhkx7ZDAyZPG72eIcYjl4yOlUM51Ih+1ukFDwC+iKPIT8Dc2nBCP5gpTTNOdb+Y
U0LLaCzqZa5QBivl6Su3y8G2k9pACiENGPWjw7ph/Ev+0UFxk/Zu7xV85XZPUQZE
xdSHrSAvLI7vcjQPC2PURNf7NwYRw0QFe/7/xah4omu1YLO6BllJDahxcnp/MgYd
/do/i0R34s4IX0mhK2E0napaBI5DsAmIt81juO3RJVXpxbe2+RIrrD53UJVSt5qg
R+y1xjT2gCTn8pIDkx3yJHX6Iftq0hPFvh3gGwIDAQABAoIBAA8/L/yFxXSOeuHh
skWaJ1L/6QpBOpcp2OO/Dt8R0nZcD3Dp8y4NaxHHQTGu/sVDIyOdQmiE19/VKyJG
g9cnaZ/ksOFk2nhIzU9jQBNNEThVcZ+OH4TLlq/WSn2Bit45mfE/cKceO9WXx9jU
CR4+fMcis6KNvoQBXbqfjvZqgoEY0bTTmhisEslpG+utKxhjKgVlFlFTb7RxTci7
OTyOpstpfvx1ZgQz+ck6rR6MhonUvHObvEpxHLIBADp+ND+8K29mMSl0/YkGJRLO
Y4NuBn2JP+x3KkFjGdRr27z5tqODLyNXNEj9o1WuiH20ssrSvuHc4PDd8r2lGAsG
xB9WpzUCgYEA7bE3Wh5R1S1RzhGQjJGyXcsEQuzoSyCvpbiMKOlggU2f4RLu1wiH
lVF8Hy7WQntlEs2Mty6hUCu2jwThX3emdXisO7/LMAsYXYPrjLwbPVEmpmgHP1Ng
7TdiskHZuc+IaEXdnLQo2cfwnwyjTGYA4G0G40dht4pDELUPAYino6UCgYEAuLJE
7bP844JShS9rXm/nwbPQcPPsKDXAIE/EvkKW9zpURiMMI/22F2ZiNFMDuSkgu0MV
PgfBhZwu0UY005Us8x1Q7iH8WgByELBIFsbTfhxlw/tCM1wDCgKTdXvB1TJqSPYZ
NJIIdNPxE+uhRvsxWcbbhyN7ZFwUKO428MxFKL8CgYA5xovH0freMGfkCQzzvi52
8fQVOHS2XjmTtKoM/70/cNjd4rY/eolKWEYtZjsaadgFnAUKOcFoNVfop60IgZLq
lux2kYYYJXpEsN4+lTKh0unsJPkuAVxcDMxmu+7qZXGotuLJRllvplPstSu0VE7+
PkIgWKd975OhqgD9xHPLKQKBgA2W4Ed1FMhQkG3IPWgnZ6/y4QVOjTOwMMCv3dP5
5k2udwDqFzyWsE0sdVFQQlffVM8ycl+sBmskQLWZKs3ejf4dTBUZXw3oNnxP3B4A
5xLCWCKBXC+XN4oHAn6EapCbMwLHSLd7fy/JYFWM4sLsPIdUgFaDH9MUi08vp88z
2GrVAoGBAKzyYoz2z71y4hC5ZXyMSefuGHRoODOgu8DYJVviJybyJ5rtLfUi1eu7
sLhhfA4oE/XiXLeGDDc4DuQ5KbrbR6X6nWI1oAT8ptwk5IoYHPfRsccaVtIwYVQr
2W0tup110R110LdwfhIsHQJONnbOu6wMuNtmJbT4ZXezXH7pa14V
-----END RSA PRIVATE KEY-----
Signature:
9cfa80431114b49b0c1c1847af7d87e055889824bb6b4a06fd0b46d85d3200c083284382a1ee73e7f20a467986d858ae9f1888039fdef6b550beaf46ffe8fe181a214089727dc5f8907d580d404df75ff18ab5bb95ab1b2a6a84247771532fd75c3252cbb1a41dbaf28d02ef84b07fdd80284354d848f191a1bd3ffd571010e50a03d070c2db25c54196cb1aa9a8d3ef579d5522dfc591528a781ef27345986c52ef2bd75cd7444ee9de4ed74b2b8ad2234c1b4aea3097897daf24f3dd144bf2d4f00b7b46e06cdc2342def8eff4f782dedc20de4b0aa5c1ead7527627815186596e0e28f23c83364c56383e13217e0497ea843607b6b923464d98e0c70d98f7
Signature is valid.
"""
✨4. 密钥序列化与反序列化
下面是一个示例,演示如何生成密钥并进行序列化和反序列化:
from cryptography.fernet import Fernet
"""
代码说明:
生成密钥:
Fernet.generate_key() 生成一个新的密钥。
序列化:
使用 key.decode('utf-8') 将密钥从字节转换为字符串,方便存储(例如保存到文件或数据库)。
反序列化:
使用 serialized_key.encode('utf-8') 将字符串转换回字节,以便恢复原始密钥。
加密与解密:
使用序列化后的密钥创建 Fernet 实例,可以对消息进行加密和解密。
"""
# 生成密钥
key = Fernet.generate_key()
fernet = Fernet(key)
# 序列化:将密钥编码为字符串以存储
serialized_key = key.decode('utf-8')
print(f"Serialized Key: {serialized_key}")
# 反序列化:将字符串解码为字节
deserialized_key = serialized_key.encode('utf-8')
# 使用反序列化的密钥进行加密和解密
fernet = Fernet(deserialized_key)
# 加密示例
message = b"Hello, World!"
encrypted_message = fernet.encrypt(message)
print(f"Encrypted Message: {encrypted_message}")
# 解密示例
decrypted_message = fernet.decrypt(encrypted_message)
print(f"Decrypted Message: {decrypted_message.decode('utf-8')}")
"""
Serialized Key: BQqk2MbwlcWt6Bt39topcwIao2Gk2M_R3doVN37EHDA=
Encrypted Message: b'gAAAAABm1S2Uwc4-4urM6bSfC3S7Az05xrJscPlP0WJlocDnXz8L6rddP3uCUVuQKsw507H6bnVsHcyj9OS1qDGVTawT9OwzQw=='
Decrypted Message: Hello, World!
"""
✨5.通信数据加密
下面是一个使用 cryptography 库和 Python 的 socket 模块来实现简单的加密通信的示例。
服务端代码(server.py):
import socket
from cryptography.fernet import Fernet
# 生成密钥
key = Fernet.generate_key()
cipher_suite = Fernet(key)
# 保存密钥到文件中(实际应用中要安全存储)
with open("secret.key", "wb") as key_file:
key_file.write(key)
# 创建 socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 65432))
server_socket.listen()
print("等待连接...")
conn, addr = server_socket.accept()
with conn:
print('连接来自', addr)
while True:
# 接收数据
encrypted_data = conn.recv(1024)
if not encrypted_data:
break
# 解密数据
decrypted_data = cipher_suite.decrypt(encrypted_data)
print("接收到:", decrypted_data.decode())
# 关闭 socket
server_socket.close()
客户端代码(client.py):
import socket
from cryptography.fernet import Fernet
# 读取密钥
with open("secret.key", "rb") as key_file:
key = key_file.read()
cipher_suite = Fernet(key)
# 创建 socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 65432))
# 发送数据
message = "你好,服务器!"
encrypted_message = cipher_suite.encrypt(message.encode())
client_socket.sendall(encrypted_message)
# 关闭 socket
client_socket.close()
运行示例
首先运行 server.py,然后它将等待客户端的连接。
然后运行 client.py,它将连接到服务器并发送一条加密消息。
⚠️ 注意事项
密钥管理:在实际应用中,密钥的存储和管理是至关重要的。根本不要将密钥硬编码在代码中。
错误处理:示例代码中缺乏错误处理,实际使用时需要考虑到网络异常等情况。
加密方式:这里使用的是对称加密,适合小规模数据,若涉及到用户身份验证或更复杂的场景,可以考虑使用 SSL/TLS 等。
通过上述代码示例,你可以了解到如何使用 cryptography 库以及 Python 的 socket 模块来实现基本的网络通信加密。
✨小结:
加密技术(Cryptography)在信息安全中扮演着重要角色,其优缺点如下:
优点
数据安全性:加密可以保护数据免受未授权访问,确保信息在存储和传输过程中的机密性。
保护隐私:通过加密,个人和组织可以保护其敏感信息,如财务数据、个人身份信息等,防止泄露。
身份验证:加密技术可以用于确保信息发送者的身份,从而防止冒充和欺诈。
数据完整性:加密方法(如哈希函数)可以检测数据在传输或存储过程中的篡改,确保数据未被更改。
合规性:遵循数据保护法律法规(如GDPR、HIPAA等)的要求,加密是一种有效的保护措施。
缺点
计算开销:加密和解密过程会增加计算资源的消耗,可能导致性能下降,特别是在大规模数据处理中。
复杂性:实现和管理加密技术可能需要专业知识,增加了系统的复杂性和管理成本。
密钥管理:加密的安全性依赖于密钥的保护和管理,密钥丢失或泄露可能导致数据无法访问或被窃取。
法律与合规风险:在某些情况下,加密可能会与法律法规产生冲突,例如某些国家对加密技术的限制。
用户体验:加密措施可能会影响用户体验,例如频繁的身份验证和数据解锁要求,可能导致操作上的不便。
总之,加密技术在提供数据保护和隐私方面具有不可替代的重要性,但其实施和管理需要谨慎考虑,以平衡安全性、性能和用户体验。