加密文件密钥环后端
项目描述
摘要
为使用keyring包而设计的加密纯文本文件密钥环后端。
描述
该项目主要针对在简单便携的文件中为纯文本密码(密钥环)提供足够安全的存储,而通常桌面环境的默认密钥环存储实现不适合这种情况。
密码学
密钥环通过密钥环密码进行保护。从密钥环密码生成一个原始的Argon2($argon2id$v=19$m=65536,t=15,p=2)
哈希,用作加密支持的一种认证AES加密方案(CCM、EAX、GCM、OCB)中明文密码的密钥,其中GCM是默认值。生成的加密数据,包括Argon2盐、nonce和MAC,会被持久化存储。该值以服务/用户ID引用的形式存储在文本文件(.ini格式)中。服务/用户ID在MAC计算中被视为关联数据。
最初,一个静态引用值,被视为密码,也会被存储,并在后续访问中用于验证密钥环密码。
攻击面
静态参考值允许某些形式的攻击,因为它加密了一个已知的值。希望Argon2散列,结合认证AES加密方案,能够将破解密钥的努力提升到一个足够高的水平。
Argon2参数化选择的方式是,截至今天(2017年),常见的桌面和服务器系统必须处理大量的CPU和内存负载来计算散列,这使得暴力攻击变得不切实际。
认证AES加密方案可以防止篡改加密数据以及其参考(服务/用户ID)。
快速入门指南
为了使您开始使用,您需要一个python3
环境和可用的git
(最好是在Linux系统上)。
您可能希望使用系统包管理器提供python包argon2-cffi
、keyring
、pycryptodome
及其依赖项(最值得注意的是SecretStorage
和cryptography
),或者使用本地venv,但这将取决于一个正常工作的C编译器和一些已安装的开发包(至少需要python-devel
和openssl-devel
)。
设置包和环境
$ git clone https://github.com/frispete/keyrings.cryptfile
$ cd keyrings.cryptfile
$ pyvenv env
$ . env/bin/activate
(env) $ pip install -e .
最后的命令应该没有错误,否则可能缺少某些开发包。
示例会话
创建一个加密密钥库,并将测试密码存储在其中。该过程会提示输入密钥库密码,该密码保护您存储的密钥库值。
(env) $ python3
Python 3.4.5 (default, Jul 03 2016, 12:57:15) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from keyrings.cryptfile.cryptfile import CryptFileKeyring
>>> kr = CryptFileKeyring()
>>> kr.set_password("service", "user", "secret")
Please set a password for your new keyring: ******
Please confirm the password: ******
>>> ^d
现在再次从密钥库中检索存储的秘密
(env) $ python3
Python 3.4.5 (default, Jul 03 2016, 12:57:15) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from keyrings.cryptfile.cryptfile import CryptFileKeyring
>>> kr = CryptFileKeyring()
>>> kr.get_password("service", "user")
Please enter password for encrypted keyring: ******
'secret'
>>> ^d
注意,KDF延迟了{set,get}_password()
操作几秒钟(在性能良好的系统上大约是1秒)。
结果
生成的文件可能看起来类似这样
(env) $ cat ~/.local/share/python_keyring/cryptfile_pass.cfg
[keyring_2Dsetting]
password_20reference =
eyJtYWMiOiAiWmVHU2lBalZ5WHd6Vmg3K2Z6TGx2UT09IiwgIm5vbmNlIjogIjB0b2dKa3RYdmdY
TVpEU1F1QkFOZFE9PSIsICJzYWx0IjogInZ2dFYzN2JvWnVLRTQzVHJ6dGd6YVE9PSIsICJkYXRh
IjogIk1UdnRzYUZ6OHdSaUZYbFBHOWZmL2dQZ0dmL3ROOG05In0=
scheme = [Argon2] AES128.GCM
version = 1.0
[service]
user =
eyJtYWMiOiAiaTJ4MWhNVGJ1S0pTZExYSXQwR0dqUT09IiwgIm5vbmNlIjogIlJ5YU1DZmkyZ0JE
NStlNHN6MGpQRWc9PSIsICJzYWx0IjogIjlIM1hJbDVhZmRZaVhkTUZyTWNOV2c9PSIsICJkYXRh
IjogImhNVC9LaTRYIn0=
值可以按如下方式解码
(env) $ python3
>>> import base64
>>> base64.decodebytes(b"""
... eyJtYWMiOiAiaTJ4MWhNVGJ1S0pTZExYSXQwR0dqUT09IiwgIm5vbmNlIjogIlJ5YU1DZmkyZ0JE
... NStlNHN6MGpQRWc9PSIsICJzYWx0IjogIjlIM1hJbDVhZmRZaVhkTUZyTWNOV2c9PSIsICJkYXRh
... IjogImhNVC9LaTRYIn0=""")
b'{"mac": "i2x1hMTbuKJSdLXIt0GGjQ==",
"nonce": "RyaMCfi2gBD5+e4sz0jPEg==",
"salt": "9H3XIl5afdYiXdMFrMcNWg==",
"data": "hMT/Ki4X"}'
讨论
json字典中的项构成加密参数和值。理论上,在不知道密码的情况下,应该足够困难
地恢复到数据
的明文值。由于将值参考(这里的服务
和用户
)与认证加密关联起来,因此会检测/拒绝修改值参考。
类层次结构继承自keyrings.alt项目,这并不容易跟随。最有趣的部分在keyrings/cryptfile/cryptfile.py,即使您不是熟练的Python程序员,它也是相当简洁的。
为了进一步控制此过程,您可能希望继承CryptFileKeyring
和/或PlaintextKeyring
。
注释
您可以在调用密钥库上的任何其他方法之前,通过提供kr.keyring_key = "your keyring password"
来避免对密钥库密码的交互式getpass()请求。以下示例显示了从环境变量KEYRING_CRYPTFILE_PASSWORD
获取密码的简单方法,如果存在的话
from getpass import getpass
from os import getenv
from keyrings.cryptfile.cryptfile import CryptFileKeyring
kr = CryptFileKeyring()
kr.keyring_key = getenv("KEYRING_CRYPTFILE_PASSWORD") or getpass()
keyring.set_keyring(kr)
测试
测试使用pytest进行。只需执行pytest
即可。使用pytest -v
执行详细的测试运行,而使用pytest -vk test_wrong_password
选择单个测试。
欢迎提供反馈。