web-dev-qa-db-ja.com

STDINでgpg2-symmetricを使用するスクリプトで使用するためにパスフレーズをキャッシュするにはどうすればよいですか?

私は秘密を保存および取得するコンピュータープログラムに取り組んでおり、サーバー上でユーザーの操作なしで実行する必要があります。

gpg-agentを使用してキャッシュされたパスフレーズを取得し、ユーザーの操作なしでgpg2 --symmetricファイル名を指定した場合でデータを暗号化および復号化するように、システム内のすべてを正常に設定しました。

ただし、これには、暗号化せずにデータをディスクに一時的に保存する必要があります。暗号化されていないデータをディスクに置きたくありません。そのため、ディスクファイルではなくSTDINとSTDOUTで動作するように変更しました。

私がテストしているコマンドはこれです:cat test.txt | gpg2 --symmetric -o test.gpg

問題は、パスフレーズをキャッシュすることができないように思われるため、毎回インタラクティブに入力する必要があることです。これは私のサーバープログラムでは機能しません。

これにgpg-preset-passphraseを使用してみました。 「KEYGRIP」が欲しいので可能かどうかはわかりませんが。私が持っている大まかなアイデアの1つは、これです。gpg2が--symmetricおよびSTDINで使用するデフォルトのキーグリップがあるかもしれません。しかし、そのアイデアがうまくいくかどうかはわかりません。

コードに--passphraseを使用してパスフレーズを指定する予定はありません。これは、コードにシークレットを格納する必要があるためです。これは、コードにアクセスできるすべてのユーザーが復号化できるようにするためです。ファイル。また、コマンドラインでパスフレーズを公開します。

私が達成しようとしていることが十分に明確であることを願っています。どんなアイデアでも大歓迎です。

1
Jason Livesay

私は最近これに苦労し、(gpgドキュメントとqaサイトを何度も見つけた後)これに出くわしました 2015スレッド それは答えに言及しています:

おそらく私が見逃しているのは、作成時と再利用時の両方で、対称パスフレーズに対して「cache_id」がどのように選択されるかです。要約できますか?私はコードを少し掘り下げましたが、それがどのように行われているかを整理しませんでした。

私が正しく覚えている場合(そしてロジックが変更されていない場合)、それはランダムに選択された8オクテットのソルト値です: http://tools.ietf.org/html/rfc4880#section-3.7.1.2 ==

.。

S2KソルトはキャッシュIDとして使用されます。

暗号化されたファイルのパケットを一覧表示することで、ソルトを取得できます。

$ echo | gpg --list-packets ~/myencryptedfile 2>&1 | grep -o '[0-9A-F]\{16\}'

0123456789ABCDEF
  • 先行するechoInappropriate ioctl for deviceエラーを強制し、ピンエントリプロンプトをバイパスします
  • 2>&1stderrを非表示
  • grep -o '[0-9A-F]\{16\}'コマンド出力からソルトを抽出します

これで、8オクテットの16進エンコードされたソルト値が得られました。

残念ながら、それは私にとって直接はうまくいきませんでした。それで、gpgコードベースをさらに見つけた後、私は このスニペット に出くわしました:

  memset (s2k_cacheidbuf, 0, sizeof s2k_cacheidbuf);
  *s2k_cacheidbuf = 'S';
  bin2hex (s2k->salt, 8, s2k_cacheidbuf + 1);
  s2k_cacheid = s2k_cacheidbuf;

核心は、2行目に付加された「S」です。私はこれが他のどこにも言及されているのを見つけることができませんでした。

だから今一緒に。ファイルを暗号化します。

$ gpg --symmetric --passphrase-fd 3 --batch --output ~/myencryptedfile <<EOF 3<<EOF3
> myencryptedcontent
> EOF
> mypassphrase
> EOF3
  • --passphrase-fd 3:ファイル記述子3にパスフレーズを指定します
  • --batch--passphrase-fdで必要
  • パスフレーズを--passphrase-fd 3経由で提供し、データをstdin(<<EOFおよび3<<EOF3)で暗号化することを、最初にcatのファイルに書き込んだり、エコーしたりするよりも好みます。 stdinに(プロセスリストのスヌーピングを恐れさせます)。ドキュメント: ヒアドキュメント (EOF構文)。
    bash以外の移植性を気にしない場合 here-strings ははるかに口当たりが良いです:
    gpg --symmetric ... ~/myencryptedfile <<<myencryptedcontent 3<<<mypassphrase

8オクテットの16進ソルト値を取得します。

$ echo | gpg --list-packets ~/myencryptedfile 2>&1 | grep -o '[0-9A-F]\{16\}'

0123456789ABCDEF

パスフレーズのリセットがgpg-agentによって許可されていることを確認してください。

$ cat ~/.gnupg/gpg-agent.conf
allow-preset-passphrase

$ gpg-connect-agent reloadagent /bye  # restart the agent after changing config

パスフレーズをプリセットします。

$ /usr/local/Cellar/gnupg/2.2.17/libexec/gpg-preset-passphrase --preset S0123456789ABCDEF <<EOF
> mypassphrase
> EOF
  • "S"がソルトのプレフィックスになりますしたがって、結果のgpg-agentcacheidは次のようになります。
    --preset S0123456789ABCDEF
  • プロセスリストに表示されないようにするための、ヒアドキュメント(EOF)を介したstdinのパスフレーズ
  • 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


ノート:

  • スクリプト内でgpg-preset-passphraseを見つけるのは、システムパスのどこにもインストールされていないため(少なくとも私のインストールでは)、煩わしいことがわかりました。ただし、gpg-connect-agentはであり、追加の手順で同じ目的に使用できます。パスフレーズを使用する前に、パスフレーズを16進エンコードする必要があります(EOFは改行を追加するため、tr -d '\n'):
$ (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
  • 私はOSXでgnupgバージョン2.2.17を実行しており、homebrew経由でインストールされています
$ gpg --version
gpg (GnuPG) 2.2.17
libgcrypt 1.8.5
2
evnp