系列文章目录
Amazevault 是一款专注于本地安全的桌面密码管理器
AmazeVault 核心功能分析,认证、安全和关键的功能
AmazeVault 快速开始,打造个人专属桌面密码管理器
文章目录
- 系列文章目录
- 前言
- 一、认证系统
- 核心组件
- 图形解锁实现
- 图形锁控件 (PatternLockWidget)
- 用户交互流程
- 图形序列生成
- UI/UX设计考量
- 密钥派生与验证
- 基于Argon2的密钥派生 (kdf.py)
- 参数配置
- 派生流程
- 认证控制器 (AuthController)
- 图形注册 (enroll)
- 图形验证 (verify)
- 状态管理与安全策略
- 错误次数限制与自动锁定
- 主密钥管理
- 用户界面与交互
- 解锁视图 (UnlockDialog)
- 恢复密钥机制
- 启用恢复密钥
- 使用恢复密钥
- 二、安全功能
- AES-GCM加密机制
- 密钥管理与初始化
- IV生成与加密流程
- 认证标签验证
- 剪贴板安全管理
- 自动清空机制
- 自动锁定策略与浮动锁按钮
- 自动锁定策略配置
- 浮动锁按钮实现原理
- 核心交互逻辑
- 数据加密存储
- 安全实践小结
- 三、辅助工具功能
- 密码生成器
- 功能实现
- 密码强度评估
- 数据备份与恢复
- 备份流程
- 恢复流程
- 审计日志分析
- 持久化与防篡改机制
- 单例模式实现
- 使用场景与最佳实践
- 使用场景
- 最佳实践
前言
本文件详细阐述了 AmazeVault 应用的认证系统、从用户交互、密钥派生、验证流程到状态管理的完整技术栈,旨在为开发者和安全研究人员提供一个全面、深入的技术参考。
接着介绍其核心安全功能,涵盖数据加密、剪贴板管理、自动锁定、内存安全等关键领域,旨在全面揭示其安全架构与实现原理。
最后讲项目中几个关键辅助工具功能,包括密码生成器、数据备份与恢复、审计日志记录以及密码强度实时评估。这些功能旨在提升用户的安全性、数据完整性和操作可追溯性。
一、认证系统
核心组件
AmazeVault 的认证系统由多个核心组件协同工作,共同保障用户数据的安全。主要组件包括:
- AuthController: 认证逻辑的核心控制器,负责处理图形注册、验证、主密钥管理等核心业务。
- PatternLockWidget: 图形解锁的UI组件,捕获用户绘制的图案并生成对应的序列。
- kdf.py: 密钥派生函数模块,使用Argon2算法将用户图案转换为高强度的加密密钥。
- AppSettings: 应用设置模块,负责持久化存储认证相关的参数和状态。
这些组件通过清晰的职责划分和接口定义,构建了一个安全、可靠且用户体验良好的认证体系。
图形解锁实现
图形锁控件 (PatternLockWidget)
PatternLockWidget 是一个自定义的PySide6控件,实现了5×5点阵的图形解锁功能。它通过重写鼠标事件来捕获用户的绘制操作。
用户交互流程
- 开始绘制: 当用户在控件区域内按下鼠标 (
mousePressEvent
),控件会确定起始节点,并初始化path
(路径)和visited
(已访问节点)集合。 - 移动绘制: 在鼠标移动过程中 (
mouseMoveEvent
),控件会持续追踪鼠标位置,确定当前悬停的节点,并将其添加到path
中(如果该节点未被访问过,或允许重复节点)。 - 结束绘制: 当用户释放鼠标 (
mouseReleaseEvent
),控件会发出sequenceFinished
信号,通知监听者用户已完成绘制。 - 键盘支持: 用户可以使用Backspace或Delete键删除路径中的最后一个节点,提供额外的交互方式。
图形序列生成
sequence()
方法将内部的二维坐标路径转换为一个逗号分隔的字符串。转换规则是将每个节点的坐标 (row, col)
映射为一个从0开始的整数:index = row * 5 + col
。例如,左上角的节点是0,其右侧的节点是1,正下方的节点是5。最终生成的字符串如 "0,1,2,7,12"
。
UI/UX设计考量
- 视觉反馈: 控件提供了丰富的视觉反馈。已访问的节点会变大并变为亮蓝色,悬停的节点会变为浅灰色,未访问的节点为深灰色。
- 动态连线: 用户绘制时,会显示一条带有流动光效的渐变连线,增强操作的直观性和科技感。
- 错误反馈:
shake()
方法实现了抖动动画,当用户输入错误时,控件会轻微抖动,提供即时的触觉反馈。
密钥派生与验证
基于Argon2的密钥派生 (kdf.py)
为了将用户绘制的图形(一个字符串序列)转换为一个安全的256位加密主密钥,amazevault使用了Argon2id算法,这是一种抗GPU和ASIC攻击的现代密码学哈希函数。
参数配置
Argon2Params
数据类定义了KDF的关键参数:
- time_cost (时间成本) : 3次迭代。控制算法的执行时间。
- memory_cost_kib (内存成本) : 64 MiB (65536 KiB)。这是Argon2的核心优势,通过消耗大量内存来抵御并行暴力破解。
- parallelism (并行度) : 2。允许算法利用多核CPU。
- hash_len (哈希长度) : 32字节 (256位)。生成的密钥长度,与AES-256加密标准匹配。
这些参数在保证安全性的同时,也考虑了在普通设备上的可用性。
派生流程
derive_master_key
函数是核心,它调用 argon2.low_level.hash_secret_raw
,传入用户图案(作为secret
)、一个随机生成的salt
和上述参数,最终输出一个32字节的密钥。
认证控制器 (AuthController)
AuthController
是整个认证流程的协调者。它利用KDF模块和用户设置来实现安全的图形验证。
图形注册 (enroll)
当用户首次设置图形时,enroll
方法被调用:
- 生成两个随机盐值:
kdf_salt
(用于KDF)和verify_salt
(用于验证哈希)。 - 使用
derive_master_key
函数,将用户图案和kdf_salt
作为输入,生成主密钥key
。 - 将
key
和verify_salt
拼接,然后使用blake2b
哈希算法生成一个32字节的verify_hash
。 - 将
kdf_salt
、verify_salt
和verify_hash
安全地存储到AppSettings
中。 - 将
key
缓存在内存中,作为当前会话的主密钥。
图形验证 (verify)
当用户尝试解锁时,verify
方法被调用:
- 检查是否已注册图形。
- 检查失败次数是否触发了延迟锁定策略。
- 使用相同的
kdf_salt
和kdf_params
,通过derive_master_key
重新派生出一个临时的主密钥。 - 将派生出的临时主密钥与存储的
verify_salt
拼接,并使用blake2b
计算哈希值。 - 使用
hmac.compare_digest
(一种防时序攻击的比较函数)将计算出的哈希值与存储的verify_hash
进行比较。 - 如果匹配,则验证成功,将派生出的主密钥缓存到内存,并重置失败计数;否则,增加失败计数并持久化。
此设计确保了即使数据库被泄露,攻击者也无法直接获取主密钥,必须通过暴力破解Argon2来尝试还原用户图案。
状态管理与安全策略
错误次数限制与自动锁定
AuthController
内部维护了一个 LockState
对象,用于跟踪失败的解锁尝试。
- 失败计数: 每次验证失败,
failed_attempts
计数器递增。 - 延迟锁定: 当失败次数达到阈值 (
failure_delay_after
) 时,后续的解锁尝试将被阻止,直到经过一段冷却时间 (failure_delay_seconds
)。这有效防止了暴力破解。 - 状态持久化: 失败计数和最后一次失败的时间戳会持久化存储在
AppSettings
中,确保应用重启后策略依然有效。
主密钥管理
- 内存缓存: 成功验证后,主密钥会被缓存在
AuthController
的_master_key
属性中,供应用其他模块使用。 - 安全清除: 当用户锁定应用或退出时,
clear_master_key
方法会被调用。该方法不仅将_master_key
置为None
,还会尝试将原始字节数组中的数据用零覆盖,以防止内存转储攻击。
用户界面与交互
解锁视图 (UnlockDialog)
UnlockDialog
是用户看到的解锁界面,它集成了 PatternLockWidget
并与 AuthController
交互。
交互流程
- 初始化:
UnlockDialog
创建时,会初始化PatternLockWidget
并设置其样式。 - 自动验证:
PatternLockWidget
的sequenceFinished
信号连接到UnlockDialog
的on_ok
方法。 - 状态反馈:
on_ok
方法调用AuthController.verify()
。根据结果,UnlockDialog
会通过_set_status
方法更新状态标签的颜色和文本(如“解锁成功”、“解锁失败”),并触发控件的shake()
动画。 - 延迟倒计时:
_timer
定时器每秒触发一次_refresh_delay_state
,用于更新界面上的剩余等待时间。
恢复密钥机制
为了防止用户遗忘图形,AmazeVault提供了恢复密钥功能。
启用恢复密钥
- 用户在已解锁状态下启用该功能。
- 系统生成一个32字节的高熵随机密钥,并编码为Base32字符串(无歧义字符)。
- 使用一个独立的、更强的Argon2参数集(基于当前参数但取最大值)和一个独立的盐值,派生出一个包裹密钥。
- 使用AES-GCM加密算法,用包裹密钥加密当前的主密钥,生成一个加密的包裹体(blob)。
- 将恢复密钥的盐值、包裹体和KDF参数安全存储。恢复密钥仅显示一次,用户必须妥善保存。
使用恢复密钥
- 用户点击“忘记图形”链接,进入恢复流程。
- 输入或粘贴恢复密钥。
- 系统使用存储的盐值和参数,派生出包裹密钥,并解密包裹体,得到原始的主密钥。
- 系统验证解密出的主密钥与当前的
verify_hash
匹配,以确保恢复密钥正确。 - 验证通过后,用户可以设置一个新的图形。系统会用新图形派生出新的主密钥,并用新密钥对所有数据进行重加密。
此机制确保了即使用户忘记了图形,也能在不丢失数据的情况下恢复访问,同时恢复密钥本身也经过了高强度的保护。
二、安全功能
AES-GCM加密机制
amazevault 使用 AES-GCM(Advanced Encryption Standard - Galois/Counter Mode)模式对数据进行加密,确保数据的机密性与完整性。该机制由 crypto/aesgcm.py
文件中的 AesGcmBox
类实现。
密钥管理与初始化
AesGcmBox
类在初始化时接收一个字节序列作为密钥。系统强制要求密钥长度必须为 16、24 或 32 字节(分别对应 AES-128、AES-192、AES-256),否则将抛出异常,确保了加密强度。
def __init__(self, key: bytes) -> None:if len(key) not in (16, 24, 32):raise ValueError("AES-GCM 密钥长度必须为 16/24/32 字节")self._key = key
IV生成与加密流程
在加密过程中,系统使用 os.urandom(12)
生成一个 12 字节的随机数作为初始化向量(IV)。该IV是每次加密操作都唯一的,防止了相同明文生成相同密文,增强了安全性。加密后的数据格式为 [12字节IV][密文||认证标签]
,其中认证标签由GCM模式自动生成。
def encrypt(self, plaintext: bytes, aad: Optional[bytes] = None) -> bytes:nonce = os.urandom(12) # 生成随机IVaes = AESGCM(self._key)ct = aes.encrypt(nonce, plaintext, aad)return nonce + ct # 拼接IV和密文+标签
认证标签验证
在解密时,系统首先从输入数据中分离出前12字节的IV和剩余部分的密文+标签。然后,使用相同的密钥和IV调用 AESGCM.decrypt
方法。该方法会自动验证认证标签的有效性。如果密文被篡改或IV不匹配,解密将直接失败并抛出异常,从而保证了数据的完整性。
def decrypt(self, blob: bytes, aad: Optional[bytes] = None) -> bytes:if not blob:return b""nonce, ct = blob[:12], blob[12:] # 分离IV和密文+标签aes = AESGCM(self._key)return aes.decrypt(nonce, ct, aad) # 自动验证认证标签
剪贴板安全管理
为防止密码等敏感信息在复制后长时间滞留在剪贴板中被恶意程序窃取,amazevault 实现了自动清空机制,由 storage/clipboard.py
文件中的 EphemeralClipboard
类负责。
自动清空机制
当用户复制密码时,copy_and_clear
方法会被调用。该方法首先将文本写入系统剪贴板,然后启动一个单次触发的定时器(QTimer
)。定时器的超时时间由 clipboard_clear_ms
设置项决定(默认6000毫秒,即6秒)。一旦定时器超时,便会执行 _clear
方法,将剪贴板内容清除。
自动锁定策略与浮动锁按钮
AmazeVault 提供了灵活的自动锁定策略和便捷的浮动锁按钮,以在用户离开时快速保护应用。
自动锁定策略配置
自动锁定策略由 storage/settings.py
文件中的 SettingsModel
类定义,主要包含两个配置项:
auto_lock_on_minimize
: 布尔值,控制应用最小化时是否自动锁定。auto_lock_inactive_minutes
: 整数值,定义应用在无操作状态下的锁定分钟数(0表示禁用)。
这些设置允许用户根据自身安全需求进行个性化配置。
浮动锁按钮实现原理
当应用被锁定时,一个半透明的浮动锁按钮(FloatingLockButton
)会出现在屏幕右下角。该按钮是一个独立的 QWidget
,通过设置 Qt.WindowStaysOnTopHint
标志使其始终位于其他窗口之上,并通过 Qt.WA_TranslucentBackground
实现透明背景。
核心交互逻辑
- 创建与显示:在
main.py
和main_window.py
中,当应用进入锁定状态时,会创建FloatingLockButton
实例并将其放置在屏幕右下角。 - 绑定解锁:通过
bind_unlock
方法,将一个解锁函数(通常会弹出解锁对话框)绑定到按钮的点击事件上。 - 倒计时显示:如果剪贴板中存有敏感信息,按钮会显示一个倒计时,提示用户信息将在何时被自动清除。
- 右键菜单:按钮支持右键菜单,提供“隐藏”和“退出”选项,方便用户管理。
数据加密存储
尽管 repository.py 文件中 configure_encryption 方法的注释表明当前使用的是“纯 SQLite 模式”,未直接使用 SQLCipher 等数据库加密方案,但所有敏感数据在写入数据库前,都已通过 AesGcmBox 进行了加密。这意味着数据库文件本身存储的是密文,即使文件被窃取,也无法直接读取明文数据。
安全实践小结
Amazevault 构建了一个全面的安全防护体系:
- 数据机密性与完整性:通过 AES-GCM 加密,确保数据在静态和传输过程中的安全。
- 临时数据保护:利用定时器自动清空剪贴板,并可选覆盖随机数据,防止敏感信息泄露。
- 会话安全:提供自动锁定和浮动锁按钮,确保用户离开时应用能快速进入安全状态。
- 内存安全:在锁定时主动清理内存中的主密钥,减少攻击面。
- 配置灵活性:通过
settings.py
集中管理各项安全策略,用户可根据需求进行调整。
这些机制协同工作,共同保障了用户密码数据的安全。
三、辅助工具功能
本节概述了文档中将深入分析的四个核心工具组件:密码生成器、数据备份、审计日志和密码强度评估。核心工具功能分布在 crypto 和 storage 目录下,而用户交互则通过 ui 模块实现。
密码生成器
password_generator.py
模块提供了安全的随机密码生成功能,支持高度自定义。
功能实现
该模块通过 generate_password
函数实现密码生成,其核心逻辑如下:
- 字符集构建:根据参数(小写、大写、数字、符号)构建候选字符集。
- 相似字符排除:可选择性地排除易混淆的字符(如 0 和 O)。
- 强制包含:确保生成的密码至少包含每种启用字符类型的一个字符。
- 随机填充:使用
os.urandom
生成加密安全的随机字节,映射到候选字符集。 - 随机打乱:使用
random.SystemRandom().shuffle
确保字符顺序的随机性。
密码强度评估
estimate_strength
函数通过以下维度评估密码强度:
- 长度:8、12、16 字符以上分别加分。
- 字符类别:包含小写字母、大写字母、数字、特殊符号的类别数。
- 综合评分:基于长度和类别数计算 0-5 分,对应“极弱”到“极强”六个等级。
数据备份与恢复
备份与恢复机制采用AES-GCM加密算法,使用主密钥派生的备份密钥对数据进行加密。备份文件为JSON格式,包含版本信息、导出时间、KDF参数、密文数据和HMAC校验码。恢复时,系统会验证HMAC以防止恶意备份注入。
备份流程
export_backup
方法执行以下步骤:
- 数据收集:从
Repository
获取所有条目和分类的完整信息。 - JSON 序列化:将数据结构转换为 JSON 字符串。
- 加密:使用主密钥通过
AesGcmBox
对 JSON 数据进行加密。 - 完整性校验:使用主密钥派生的 MAC 密钥对密文计算 HMAC-SHA256,确保数据未被篡改。
- 元数据打包:将版本、时间、KDF 参数、密文和 MAC 打包成一个 JSON 对象。
恢复流程
import_backup
方法执行以下步骤:
- MAC 校验:使用相同的派生密钥重新计算 MAC,并与备份文件中的 MAC 进行比较,确保数据完整性。
- 解密:使用主密钥解密数据。
- 冲突处理:在交互模式下,对于标题、用户名、URL 相同但其他字段不同的条目,弹出对话框让用户选择处理方式(跳过、覆盖、合并标签、自定义合并)。
- 数据合并:根据用户选择或默认策略,将导入的数据与现有数据合并。
审计日志分析
audit.py
模块实现了轻量级、线程安全的审计日志记录。
持久化与防篡改机制
审计日志的持久化机制设计充分考虑了性能和可靠性。系统采用异步批量写入策略,通过独立的后台线程处理日志写入,避免阻塞主线程。
单例模式实现
系统通过全局变量_singleton和两个辅助函数init_audit_with_settings与get_audit来实现单例模式。
使用场景与最佳实践
使用场景
- 密码生成器:在创建新账户或需要高强度密码时使用。
- 数据备份:在更换设备、系统升级或定期归档前执行。
- 审计日志:用于安全审查,追踪账户的登录、修改等关键操作。
- 密码强度评估:在设置或修改密码时,实时检查密码安全性。
最佳实践
- 密码生成:建议启用所有字符类型并排除相似字符,长度至少 12 位。
- 数据备份:定期备份,并将备份文件存储在安全位置。导入前务必验证 MAC。
- 审计日志:定期检查日志,关注异常登录或大量数据修改事件。
- 密码管理:利用实时评估功能,确保所有存储的密码达到“良好”或更高强度。