Jas*_*say 3 linux security encryption bash gnupg
我正在开发一个存储和检索秘密的计算机程序,并且需要在服务器上无需用户交互的情况下运行。
我已经成功地在系统中设置了所有内容,用于检索缓存的密码短语,而无需用户交互来在指定文件名时gpg-agent
加密和解密数据。 gpg2 --symmetric
但是,这需要我将数据暂时存储在磁盘上而不加密。我不想将未加密的数据放在我的磁盘上。所以现在我已经更改了使用 STDIN 和 STDOUT 而不是磁盘文件的内容。
我正在测试的命令是这样的:cat test.txt | gpg2 --symmetric -o test.gpg
。
问题是,现在似乎不可能缓存密码,因此我每次都必须以交互方式输入它。这对我的服务器程序不起作用。
我已经尝试使用 gpg-preset-passphrase 来实现此目的。我不知道这是否可能,因为它需要一个“KEYGRIP”。我的一个粗略想法是:也许 gpg2 与 --symmetry 和 STDIN 一起使用一些默认的 keygrip。但我不知道这个想法是否会成功。
我不打算在我的代码中使用 --passphrase 指定密码,因为这意味着我需要在代码中存储秘密,而我不会这样做..并且它将允许任何可以访问代码的人解密文件。它还会在命令行上公开密码。
我希望我想要实现的目标足够清楚。任何想法表示赞赏。
小智 5
我最近为此苦苦挣扎,(在 gpg 文档和 qa 网站上无休止地摸索之后)发现了这个2015 年的帖子,其中提到了答案:
也许我缺少的是如何在创建时和重用时为对称密码选择“cache_id”。你能总结一下吗?我仔细研究了代码,但没有弄清楚它是如何完成的。
如果我没记错的话(逻辑没有改变),它是一个随机选择的 8 字节盐值: https://www.rfc-editor.org/rfc/rfc4880#section-3.7.1.2
...
S2K salt 用作缓存 ID。
您可以通过列出加密文件的数据包来获取盐:
$ echo | gpg --list-packets ~/myencryptedfile 2>&1 | grep -o '[0-9A-F]\{16\}'
0123456789ABCDEF
Run Code Online (Sandbox Code Playgroud)
echo
力量Inappropriate ioctl for device
错误,绕过 pinentry 提示2>&1
隐藏标准错误grep -o '[0-9A-F]\{16\}'
从命令输出中提取盐现在我们有了 8 个八位字节的十六进制编码盐值。
不幸的是,这对我来说并没有直接作用。因此,在对 gpg 代码库进行了更多的摸索之后,我发现了这个片段:
$ echo | gpg --list-packets ~/myencryptedfile 2>&1 | grep -o '[0-9A-F]\{16\}'
0123456789ABCDEF
Run Code Online (Sandbox Code Playgroud)
关键是第二行前面的“S”。我在其他地方找不到提到这一点。
所以现在大家在一起了。加密文件:
$ gpg --symmetric --passphrase-fd 3 --batch --output ~/myencryptedfile <<EOF 3<<EOF3
> myencryptedcontent
> EOF
> mypassphrase
> EOF3
Run Code Online (Sandbox Code Playgroud)
--passphrase-fd 3
:通过文件描述符 3 提供密码--batch
: 需要与--passphrase-fd
--passphrase-fd 3
和要加密的数据,而不是最初将其写入文件 for ,或将其回显到 stdin (这让我担心进程列表窥探)。文档:此处文档(EOF 语法)。Bash这里的字符串在语法上更容易接受(例如),但会将密码短语保留在 bash 历史记录中,因此在此用例中最好避免使用它们。<<EOF
3<<EOF3
cat
gpg --symmetric ... ~/myencryptedfile <<<myencryptedcontent 3<<<mypassphrase
获取 8 字节十六进制盐值:
$ echo | gpg --list-packets ~/myencryptedfile 2>&1 | grep -o '[0-9A-F]\{16\}'
0123456789ABCDEF
Run Code Online (Sandbox Code Playgroud)
确保 gpg-agent 允许重置密码:
$ cat ~/.gnupg/gpg-agent.conf
allow-preset-passphrase
$ gpg-connect-agent reloadagent /bye # restart the agent after changing config
Run Code Online (Sandbox Code Playgroud)
预设密码:
$ /usr/local/Cellar/gnupg/2.2.17/libexec/gpg-preset-passphrase --preset S0123456789ABCDEF <<EOF
> mypassphrase
> EOF
Run Code Online (Sandbox Code Playgroud)
--preset S0123456789ABCDEF
ERR 67108924 Not supported <GPG Agent> - no --allow-preset-passphrase
,则需要添加allow-preset-passphrase
并~/.gnupg/gpg-agent.conf
重新启动代理(见上文)gpg-preset-passphrase
可能有所不同。最后,解密文件!
$ gpg --decrypt --pinentry-mode loopback ./myencryptedfile
gpg: AES encrypted data
gpg: encrypted with 1 passphrase
myencryptedcontent
Run Code Online (Sandbox Code Playgroud)
gpg-preset-passphrase
在我的脚本中定位很烦人,因为它没有安装在系统路径上的任何位置(至少没有安装在我的安装中)。然而,gpg-connect-agent
通过额外的步骤,可以用于相同的目的。您只需要在使用密码之前对其进行十六进制编码(tr -d '\n'
因为 EOF 添加换行符):$ (tr -d '\n' | hexdump -v -e '/1 "%02X"' && echo) <<EOF
> mypassphrase
> EOF
6D7970617373706872617365
$ gpg-connect-agent <<EOF
> preset_passphrase S0123456789ABCDEF -1 6D7970617373706872617365
> EOF
OK
# now decryption should work as above
Run Code Online (Sandbox Code Playgroud)
$ gpg --version
gpg (GnuPG) 2.2.17
libgcrypt 1.8.5
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2748 次 |
最近记录: |