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
クロージャを使用した例です。
|
|