OpenPGPはPGP(Pretty Good Privacy)をベースとした暗号化フォーマットです。
Go言語でもgolang.org/x/crypto/openpgp
という準標準パッケージで提供されています。
PGPは公開鍵暗号としてメールの暗号化等でよく使用されますが、パスフレーズを用いた対称暗号として使用することもできますので、今回はこちらを紹介します。
TL;DR
- 暗号化には
SymmetricallyEncrypt()を使用する - 復号には
ReadMessage()を使用するprompt次第で無限ループする恐れがあるので注意
暗号化
x/crypto/openpgpパッケージでパスフレーズを用いてファイルを暗号化するには、SymmetricallyEncrypt関数を使用します。
シグネチャは次のようになっています。
| |
順番に見て行きます。まずは引数から。
第一引数であるciphertextには、暗号化されたテキストを出力するio.Writerを与えます。*os.Fileなどを与えてもいいですが、*bytes.Bufferなどを与えてその後*os.Fileにコピーする方が良いでしょう。可読なテキストではなく、バイト列が出力されます。
第二引数のpassphraseはその名の通り、パスフレーズを与えます。
第三引数のhintsには暗号化するファイルのメタデータなどを含むことができますが、単純にnilを与えても良いです。
第四引数のconfigで暗号化方式や乱数エントロピーソース、圧縮アルゴリズムなどを設定することができます。設定しなければ乱数としてcrypto/rand.Readerが、ハッシュ関数としてSHA-256が、暗号化関数としてAES-128が、現在時刻としてtime.Nowが、RSAのビット数として2048がそれぞれ使用されます。圧縮はされません。
返り値は二値で、io.WriteCloserとerrorです。返り値のio.WriteCloserに暗号化したい内容を書き込むことで暗号化が行われます。必ずCloseする必要があるので忘れないように注意しましょう。
使用例
| |
復号
暗号化したファイルを復号するには、ReadMessage関数を使用します。Decrypt〜のような関数ではないので注意が必要でしょう。関数のシグネチャは次のようになっています。
| |
こちらも順に見て行きましょう。
第一引数のio.Readerには暗号化されたファイルを与えます。読み込みですから、*os.Fileを直接与えてもいいかもしれません。
第二引数は復号に使用する鍵へのKeyRingですから、パスフレーズで暗号化した今回はnilを与えます。
第三引数であるpromptがこの関数の肝で、パスフレーズを返すコールバック関数を与えます。PromptFunctionの定義は次のようになっています。
| |
今回の用途の場合は引数を使用する必要はありません。基本的には単純にパスフレーズを返す関数とするか、標準入力等からパスフレーズを読み込んで返す、という関数として作成すれば良いでしょう。
一点だけ注意点があり、ドキュメントに次のような記載があります。
If the decrypted private key or given passphrase isn’t correct, the function will be called again, forever.
返されたパスワードが間違っていると、永遠にこの関数が呼ばれ続けます。そのため、二度目に呼ばれた時にエラーを返すように、なんらかの対策が必要です。 例えば、次のようなクロージャを作成しても良いでしょう。
| |
第四引数のconfigは暗号化の時に使用したものと同じものを使用します。
返り値の*MessageDetailsに復号された内容が含まれています。この構造体はいくつかのメタデータを含みますが、実際のデータはMessageDetails.UnverifiedBodyというio.Readerに格納されています。
使用例
前節で紹介したpromptFnクロージャを使用した例です。
| |
