使用加密技术实现个人密码本保护
整体设计思路
使用多层安全设计开发一个密码保险箱系统,具体包含:
1.加密层:使用AES-256-GCM认证加密保护数据
2.密钥管理:使用PBKDF2-HMAC从主密码派生加密密钥
3.安全存储:文件格式包含盐值、IV和加密数据
4.内存保护:敏感数据仅在需要时驻留内存
5.用户交互:命令行菜单系统,密码输入隐藏
代码实现层面
下面逐部分详细解释;
导入模块部分
import os # 文件系统操作
import json # JSON数据序列化
from getpass import getpass # 安全密码输入,不会在屏幕上显示用户输入的内容。
from cryptography.hazmat.primitives import hashes # 哈希算法
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC # 密钥派生
from cryptography.hazmat.primitives.ciphers.aead import AESGCM # 加密算法
from cryptography.hazmat.backends import default_backend # 加密后端
from cryptography.exceptions import InvalidTag # 解密失败异常
import base64 # Base64编码
- 安全设计:选择行业标准的加密组件(AES-GCM,PBKDF2)
- 功能分离:每个模块负责特定安全功能
PassWord Vault类
初始化方法
def __init__(self, file_path):self.file_path = file_path # 密码库文件路径self.data = {"entries": []} # 内存中的明文数据self.key = None # 加密密钥(解锁后设置)self.salt = None # 密钥派生盐值
- 安全状态:初始时密钥为空(保险箱锁定状态)
- 数据结构:使用字典存储密码条目,便于扩展
创建密码库
def create_vault(self, master_password):if os.path.exists(self.file_path):raise FileExistsError("密码库文件已存在")self.salt = os.urandom(16) # 生成16字节随机盐值self.key = self._derive_key(master_password, self.salt) # 派生密钥self.data = {"entries": []} # 初始化空数据结构self._save_vault() # 加密保存
- 安全关键:每次创建生成唯一盐值
- 防御措施:防止覆盖现有密码库
解锁密码库
def unlock_vault(self, master_password):if not os.path.exists(self.file_path):raise FileNotFoundError("密码库文件不存在")with open(self.file_path, "rb") as f:file_data = f.read() # 读取整个文件# 解析文件结构: salt(16) + iv(12) + encrypted_dataself.salt = file_data[:16]iv = file_data[16:28]ciphertext = file_data[28:]self.key = self._derive_key(master_password, self.salt) # 派生密钥try:aesgcm = AESGCM(self.key)plaintext = aesgcm.decrypt(iv, ciphertext, None) # 解密数据self.data = json.loads(plaintext.decode('utf-8')) # 解析JSONexcept InvalidTag: # 认证失败self._clear_sensitive_data() # 清除敏感数据raise ValueError("密码错误或文件损坏")
- 文件格式:固定格式salt+iv+ciphertext
- 错误处理:捕获Invaild Tag异常防止篡改攻击
- 内存安全:解密失败立即清楚密钥
添加密码条目
def add_entry(self, site, username, password, notes=""):if not self.key:raise RuntimeError("请先解锁密码库")new_entry = {"id": len(self.data["entries"]) + 1, # 自增ID"site": site,"username": username,"password": password,"notes": notes,"created_at": self._current_timestamp() # 时间戳}self.data["entries"].append(new_entry)self._save_vault() # 立即保存
- 审计跟踪:记录创建时间戳
- 即时保存:添加后立即加密保存
密钥派生函数
def _derive_key(self, master_password, salt):kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), # SHA-256哈希length=32, # 256位密钥salt=salt,iterations=100000, # 10万次迭代backend=default_backend())return kdf.derive(master_password.encode('utf-8'))
- 安全参数:高迭代次数防止暴力破解
- 密钥长度:256位满足AES-256要求
保存密码库
def _save_vault(self):if not self.key:raise RuntimeError("未初始化密钥")plaintext = json.dumps(self.data).encode('utf-8') # 序列化iv = os.urandom(12) # 新随机IV(每次保存不同)aesgcm = AESGCM(self.key)ciphertext = aesgcm.encrypt(iv, plaintext, None) # 加密with open(self.file_path, "wb") as f:f.write(self.salt) # 盐值f.write(iv) # 初始向量f.write(ciphertext) # 加密数据
- 加密最佳实践:每次保存使用新IV
- 文件格式:盐值+IV+密文
- 原子操作:直接覆盖文件(简单实现,生产环境应使用临时文件)
安全清楚
def _clear_sensitive_data(self):self.key = None # 清除密钥# 模糊化密码字段if 'password' in self.data:for entry in self.data["entries"]:entry["password"] = "******"self.data = {"entries": []} # 重置数据结构
- 内存清楚:主动清除密钥引用
- 数据模糊:密码字段替换为占位符
- 状态重置:清楚数据回到初始状态
辅助功能
强密码生成
def generate_strong_password(length=16):import secretsimport stringalphabet = string.ascii_letters + string.digits + "!@#$%^&*()"return ''.join(secrets.choice(alphabet) for _ in range(length))
- 密码学安全:使用secrets模块(非random)
- 字符集:包含大小写字母、数字和符号
用户界面
主菜单系统
def main_menu():print("\n" + "=" * 40)print(" 安全密码本管理系统")print("=" * 40)print("1. 创建新密码库")# ... 其他选项 ...return input("请选择操作: ")def main():vault = None # 密码库实例while True:choice = main_menu()# 处理9种用户选择
- 状态管理:vault对象在解锁后保持
- 操作引导:清晰的菜单选项
关键交互点
1. 密码确认
master_password = getpass("设置主密码: ")
confirm_password = getpass("确认主密码: ")
if master_password != confirm_password:print("密码不匹配!")
2. 密码显示确认
confirm = input("\n显示密码?(y/n): ").lower()
if confirm == 'y':print(f"密码: {entry['password']}")
3.自动生成密码
password = getpass("密码(留空生成随机密码): ")
if not password:password = generate_strong_password()
最终效果
在命令行使用操作序列号就可以对密码库进行操作了。
后续,为了使用简便,会将密码本从命令行交互调整为移动应用交互操作的模式。