还在用浏览器自带的密码管理器?亦或是用 Excel 表格记录密码?这种方式在安全性上存在很大隐患。本文将通过一个 Day 29 - 密码管理器开发 - Python学习笔记 的实战项目,带你从零开始构建一个简易但安全的密码管理工具。它将涉及到密码的生成、加密存储以及安全访问等关键环节。相比于将所有密码明文存储在文件中,一个好的密码管理器应当具备加密存储和方便检索的能力。考虑到后续的扩展性,我们甚至可以考虑将其部署到云端,并使用 Nginx 作为反向代理,提升系统的并发连接数和负载均衡能力。
底层原理深度剖析
密码安全的关键:加密算法
密码管理器的核心在于密码的加密存储。这里我们将使用 cryptography 库,它提供了多种加密算法,包括对称加密算法(如 AES)和非对称加密算法(如 RSA)。
- 对称加密:加密和解密使用相同的密钥,速度快,但密钥管理是个问题。
- 非对称加密:加密和解密使用不同的密钥(公钥和私钥),安全性高,但速度较慢。
考虑到性能和安全性,我们可以结合使用这两种算法。例如,使用 RSA 加密一个随机生成的 AES 密钥,然后使用 AES 密钥加密密码数据。这样既保证了密钥的安全性,又保证了数据加密的速度。
安全存储:防止中间人攻击
仅仅加密数据还不够,我们需要安全地存储加密后的数据和密钥。常见的做法是将加密后的数据存储在本地文件中,并将密钥存储在操作系统提供的安全存储中(例如,Windows 的 Credential Manager 或 macOS 的 Keychain)。另一种方法是使用数据库存储加密后的数据,例如 MySQL 或 PostgreSQL。如果数据量较大,可以考虑使用云数据库,并配合宝塔面板进行管理。
密钥管理:永远不要硬编码
最糟糕的做法是将密钥硬编码在代码中。正确的做法是:
- 密钥派生函数(KDF):使用用户的主密码(Master Password)作为输入,通过 KDF(如 PBKDF2 或 Argon2)生成加密密钥。KDF 会对主密码进行加盐和多次哈希,增加破解难度。
- 随机数生成:使用
secrets模块生成安全的随机数,用于初始化向量(IV)和盐值(Salt)。
代码实现:密码管理器的核心模块
以下是一个简化的密码管理器核心模块的代码示例:
import os
import secrets
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.backends import default_backend
import base64
# Key Derivation Function (KDF)
def derive_key(master_password: str, salt: bytes) -> bytes:
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32, # AES-256 key size
salt=salt,
iterations=100000, # Adjust for security vs performance
backend=default_backend()
)
key = kdf.derive(master_password.encode())
return base64.urlsafe_b64encode(key)
# Encryption Function
def encrypt_password(password: str, master_password: str) -> bytes:
salt = secrets.token_bytes(16) # Generate a random salt
key = derive_key(master_password, salt)
f = Fernet(key)
encrypted_password = f.encrypt(password.encode())
return salt + encrypted_password # Store salt with ciphertext
# Decryption Function
def decrypt_password(encrypted_password: bytes, master_password: str) -> str:
salt = encrypted_password[:16]
ciphertext = encrypted_password[16:]
key = derive_key(master_password, salt)
f = Fernet(key)
decrypted_password = f.decrypt(ciphertext).decode()
return decrypted_password
# Example usage
master_password = "my_secret_master_password" # Replace with user input
password_to_encrypt = "my_secret_password"
encrypted = encrypt_password(password_to_encrypt, master_password)
decrypted = decrypt_password(encrypted, master_password)
print(f"Encrypted password: {encrypted}")
print(f"Decrypted password: {decrypted}")
代码解释:
derive_key函数使用 PBKDF2HMAC 从主密码派生加密密钥。encrypt_password函数使用 Fernet(基于 AES 的对称加密)加密密码,并将盐值与加密后的密码一起存储。decrypt_password函数使用 Fernet 解密密码。
重要提示: 请务必将 master_password 替换为用户实际输入的主密码。同时,可以调整 PBKDF2HMAC 的迭代次数,以平衡安全性和性能。
实战避坑经验总结
- 主密码强度:强制用户设置高强度的密码,并定期更换。
- 密钥存储安全:避免将密钥存储在代码或配置文件中。可以使用操作系统提供的安全存储或硬件安全模块 (HSM)。
- 防止重放攻击:可以使用时间戳或序列号来防止重放攻击。
- 数据备份:定期备份加密后的数据,以防止数据丢失。
- 代码审查:定期进行代码审查,以发现潜在的安全漏洞。
- 依赖管理:使用
pip或conda等工具管理依赖,并定期更新依赖包,以修复安全漏洞。 - 数据库优化:如果使用数据库存储密码,注意配置数据库连接池,避免频繁创建和销毁连接,影响性能。
通过学习和实践 Day 29 - 密码管理器开发 - Python学习笔记 这个项目,你将对密码安全和加密算法有更深入的理解。记住,安全是一个持续的过程,需要不断学习和改进。
冠军资讯
代码一只喵