OpenSSLを使ってファイルをお手軽に暗号化できることを知ったので、メモを兼ねて紹介したいと思います。
実行環境について
基本的にはOpenSSLかLibreSSLがインストールされていればよいです。
私はmacOSとLinuxのOpenSSLで確認しましたが、WindowsでもOpenSSLをインストールすれば利用可能だと思います。
一部、macOSのバージョン(Big Sur)によっては使えないコマンドがあるようですが、代替手段はあります(後述)。
ファイル暗号化に使えるコマンド
OpenSSLにはたくさんのサブコマンドがありますが、今回紹介するファイル暗号化に使えるサブコマンドと特徴は次のとおりです。
-
openssl enc- 暗号方式: 共通鍵暗号
- パスワードで暗号化と復号
- ファイル形式: ブロック暗号のバイナリデータ(オプションでBase64処理も追加できる)
- 暗号方式: 共通鍵暗号
-
openssl cms- 暗号方式: 公開鍵暗号
- X.509証明書で暗号化して、秘密鍵で復号
- ファイル形式: MIME形式のテキストデータ(ヘッダとボディのやつ)
- macOS Big Surでは使えない
- Homebrewで別途OpenSSLを入れるか、次の
openssl smimeで代替可能
- Homebrewで別途OpenSSLを入れるか、次の
- 暗号方式: 公開鍵暗号
-
openssl smime-
openssl cmsとほぼ同じ(データの互換性もある) - 一部の
openssl cmsサブコマンドが使えない環境ではこちらを使うとよい
-
openssl enc
共通鍵暗号でファイルの暗号化・復号を行うコマンドです。
暗号化に使用する鍵はパスワードから導出されますが、別途鍵ファイルやIV(初期化ベクトル)などを直接指定するような使い方も可能です(本記事では割愛します)。
暗号化
次のコマンドはfoo.txtというファイルを暗号化し、encrypted_foo.datファイルとして保存する例です。
# 暗号化
openssl enc -aes256 -pbkdf2 -md sha-256 -in foo.txt -out encrypted_foo.dat
復号
次のコマンドはencrypted_foo.datというファイルを復号し、decrypted_foo.txtファイルとして保存する例です。
# 復号
openssl enc -d -aes256 -pbkdf2 -md sha-256 -in encrypted_foo.dat -out decrypted_foo.txt
openssl encでよく使うオプション
主に次のようなオプションがあります(全てではないです)。
-
-d: 復号 -
-pbkdf2: 鍵の導出にPBKDF2を使用する(推奨) -
-md: 鍵の導出に使用するメッセージダイジェスト関数(sha-256,md5など)- OpenSSLのバージョンによってデフォルト値が異なるので、トラブルを避けるためにも明示的に指定したほうがよい
- OpenSSL 1.0.2以前:
md5 - OpenSSL 1.1.0以降:
sha-256
-
-base64: 暗号化(または復号)の後(前)にBase64処理を行う -
-in: 入力ファイル -
-out: 出力ファイル -
-p: salt, key, ivを表示する -
-P: salt, key, ivを表示するだけ(暗号復号処理は行わない) -
-list: サポートしている暗号スイートのリストを表示する
openssl cms
S/MIME 3.1に準拠したメッセージの暗号化・復号・署名・署名検証のためのコマンドです。
公開鍵で暗号化を行います。
ファイル暗号化というよりはメールの暗号化や署名のための機能ですが、ファイルの暗号化機能として活用することも可能です。
macOS Big SurではLibreSSLのバージョンの都合で利用できません。
Homebrewで別途最新のOpenSSLをインストールするか、次のopenssl smimeで代替可能です。
前準備: 鍵と証明書の作成
まず、RSA鍵(key.pem)とX.509証明書(cert.pem)を作成する必要があります(ファイル名は一例です)。
証明書の/CN=aliceのaliceの部分は、証明書のCommon Nameです。自分のアカウント名などにすればよいでしょう(ちなみに、Webサーバー用の証明書の場合はドメイン名にします)。
# 鍵の生成
openssl genrsa -out key.pem 4096
# 証明書の生成(自己署名証明書)
# "alice"の部分は自分のアカウント名などにします
openssl req -new -x509 -key key.pem -out cert.pem -days 36500 -subj "/CN=alice"
# 証明書の内容の確認
openssl x509 -in cert.pem -noout -subject -dates
暗号化
次のコマンドはcert.pemという証明書を使って、foo.txtを暗号化し、encrypted_cms_foo.txtとして保存する例です。
# 暗号化
openssl cms -encrypt -aes256 -binary -in foo.txt -out encrypted_cms_foo.txt cert.pem
復号
次のコマンドはkey.pemという秘密鍵を使用し、encrypted_cms_foo.txtを復号し、decrypted_cms_foo.txtとして保存する例です。
# 復号
openssl cms -decrypt -inkey key.pem -in encrypted_cms_foo.txt -out decrypted_cms_foo.txt
暗号化されたファイルについて
openssl cmsで暗号化されたファイルの中身は次のようなテキストファイルになります。
いくつかのヘッダとBase64エンコードされたペイロードで構成されています。
MIME-Version: 1.0
Content-Disposition: attachment; filename="smime.p7m"
Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name="smime.p7m"
Content-Transfer-Encoding: base64
MIICoAYJKoZIhvcNAQcDoIICkTCCAo0CAQAxggJIMIICRAIBADAsMBQxEjAQBgNV
BAMMCXluYWthbXVyYQIUF5dLx3pVTTQT5m6Z64PQVWn+KfwwDQYJKoZIhvcNAQEB
BQAEggIAPvjGzsikMqHesMO90wJdKJxWDH0fqAUIqubTroPu09HZ6XrXWeWJ79fC
HYM9iAILv...
openssl smime
openssl cmsと使い方は同じです(サブコマンドのcmsがsmimeになっただけ)。
# 鍵の生成
openssl genrsa -out key.pem 4096
# 証明書の生成(自己署名証明書)
openssl req -new -x509 -key key.pem -out cert.pem -days 36500 -subj "/CN=alice"
# 証明書の確認
openssl x509 -in cert.pem -noout -subject -dates
# 暗号化
openssl smime -encrypt -aes256 -binary -in foo.txt -out encrypted_smime_foo.txt cert.pem
# 復号
openssl smime -decrypt -inkey key.pem -in encrypted_smime_foo.txt -out decrypted_smime_foo.txt
まとめ
それぞれ一長一短あるかと思いますが、OpenSSLを使って手軽にファイルを暗号化することができました。
encのほうは前準備の必要もなく、パスワードで簡単に扱えるのが良いですね。
プログラムなどで暗号化の実装をしているときの検証にも使えたりします。
cms / smimeのほうは、鍵と証明書を管理しないといけないのがやや面倒ですが、処理するときにいちいちパスワードを入力しなくてもよいのが楽です。
また、テキストファイルになるので、やり取りがしやすくなります。