OpenSSLを使って暗号化した情報を復号化しようとしたところ、こんなエラーに遭遇しました。
ネットで探してもなかなか解決策が見つからず、苦労したので理解できたことをメモとして残しておこうと思います。
# openssl aes-256-cbc -d -in hoge -pass pass:foo > piyo
bad decrypt
40D74304EF7F0000:error:1C800064:Provider routines:ossl_cipher_unpadblock:bad decrypt:../providers/implementations/ciphers/ciphercommon_block.c:124:
エラーが発生した状況
- 自身のMac(macOS: 12.6.3)でとあるデータを暗号化した
- git push時にgithub actionsで実行しているubuntu上で復号化を実行した
どうやって解決したか
暗号化するときと復号化するときの両方で、同じメッセージダイジェスト方式を指定する(-md md5
などのオプションをつける)。
# 暗号化する時
openssl enc -aes-256-cbc -e -in foo -pass pass:bar > hoge -md md5
# 復号化するとき
openssl enc -aes-256-cbc -d -in hoge -pass pass:bar > piyo -md md5
※ 上記の例は以下の環境(OpenSSL3でもLibreSSL)でも動くことを確認しています。
動作環境
- macOS: 12.6.3
- LibreSSL 2.8.3 ← デフォルトでインストールされているOpenSSL
- OpenSSL: 3.0.8 7 Feb 2023 (Library: OpenSSL 3.0.8 7 Feb 2023) ← homebrewで入れたやつ
- ubuntu: 22.04.1
- OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
分かったこと
調べていると、MacとUbuntuで実行しているOpenSSLのバージョンが違うことに気づきました。
さらに調べていくとMacにインストールされているデフォルトのOpenSSLは
実際にはLibreSSLというOpenSSL 1.0.1からフォークした別のライブラリなのだそうです。
(フォークした背景にはいろいろ根深いものがありそうです)
そして、OpenSSL3とLibreSSL(OpenSSL2)では -md
を指定しなかったときの
デフォルトのメッセージダイジェストの方式が異なるそうです。
OpenSSL は 1.1.0 を境にダイジェストアルゴリズムのデフォルト値が md5 から sha256 に変更されています。
確かにOpenSSL3だと-md
のデフォルト値はsha-256
となっています。
-md digest
Use the specified digest to create the key from the passphrase. The default algorithm is sha-256.
一方、LibreSSLのマニュアルには明確にどっちということは書いてありませんでした(むしろsha-1とか書いてある)。
# man openssl
ENC
openssl enc -ciphername [-AadePp] [-base64] [-bufsize number] [-debug] [-in file] [-iv IV] [-K key] [-k password] [-kfile file] [-md digest] [-none] [-nopad] [-nosalt] [-out file]
[-pass arg] [-S salt] [-salt]
-md digest
Use digest to create a key from a pass phrase. digest may be one of md5 or sha1.
解決策としてはこちらの記事にも書いてあったとおり
-md
を明示的に指定しするということで解決できました。
ググってもなかなか探し当てられずハマってしまったので、この記事が誰かのお役に立てられたら幸いです。(ちなみに最初にヒントを得ることができたのは技術評論社さんから出版されている書籍の補足のページでした)
補足
なおOpenSSL3では-pbkdf2
(か-iter
)オプションをつけないと、以下のようなWarningが表示されます。
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
問題なく暗号化・復号化できますが、OpenSSL3以降の環境だけで使うことが明らかな場合は、このオプションをつけておいたほうが良さそうです。(bruteforceのような総当り攻撃に対する試行回数の制限や、その類の脆弱性に対するオプションのようです)
https://ja.wikipedia.org/wiki/PBKDF2
最後に
なお、本記事で取り扱っている内容はセキュリティに関する情報であり、誤解や誤用によってリスクが発生するものでもあります。鵜呑みにせず、あくまで参考程度にしていただき、各自一次リソースや専門家や経験者による確認や相談もしていただければと思います。
また本記事で間違っているところがあったら指摘していただけますと幸いです。