質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
OpenSSL

OpenSSLはSSL/TLSのプロトコルと一般的な暗号のライブラリを導入するオープンソースのソフトウェアのツールキットです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

1回答

4394閲覧

OpenSSLにて暗号化された文をPHPのopenssl関数で復号したい

takemoto_piano

総合スコア0

OpenSSL

OpenSSLはSSL/TLSのプロトコルと一般的な暗号のライブラリを導入するオープンソースのソフトウェアのツールキットです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2021/10/26 08:26

前提・実現したいこと

暗号方式aes-256-cbcと暗号鍵“xxx”を用いて暗号化した後base64でエンコードされた文を復号したいです。
以下のようなソースコードで動作させましたがうまく動きませんでした。
エラーは発生しておらず、なにも出力されていない状態です。

発生している問題・エラーメッセージ

復号された文が出力されるはずが何も出力されない。

該当のソースコード

PHP

1<?php 2 3$encrypted = '暗号化された文字列'; 4$password = 'xxxをbase64でエンコードした文字列'; 5$decrypted = openssl_decrypt( $encrypted, 'aes-256-cbc' ,$password,); 6 echo $decrypted ; 7

試したこと

passwordにはbase64でエンコードしていない素の暗号鍵も入力しましたりしてみましたがうまくいきませんでした。

補足情報(FW/ツールのバージョンなど)

PHP初心者のため何卒ご教授いただければ幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

OpenSSLにて暗号化された

opensslコマンドかと推測しますが、暗号化した方法を詳らかにしてください。
以下、opensslコマンドでの暗号化と仮定しますが、この場合鍵の指定法は大きく2通りあります。付け加えると、鍵だけでなくIV(初期化ベクトル)というデータも必要です。

  1. パスワードを与えてsalt(ツールがランダム生成)を加えて変換して鍵・IVを生成
  2. 鍵・IVを明示的に指定

ところが、質問の中にIVの話が出てきません。ということは、1. のパスワードのことを「鍵」と誤認識しているのではないかと思います。
PHPのopenssl_encrypt/decryptは 2. の方に対応した機能なので、1. しか意識してない状態では使えません。

…ただ、1. で指定したパスワードから鍵・IVを知る方法は、PHPの中ではおそらくありません。
ということで、今回は openssl コマンドを直接呼び出して復号する他はなさそうに思います。
→ 追記: opensslの内部動作に依存した方法ではありますが、鍵・IVを知る方法がありました。末尾に追記します

参考までに、以下 1, 2 の方法の違いです。

===
例えば abc.txt を、opensslコマンドで、パスワード "xyz" で暗号化して enc.dat に保存するとします ( base64化はナシとします )。これは 1. に沿った方法です。

$ openssl enc -aes-256-cbc -pass pass:xyz -in abc.txt -out enc.dat

同じく 1. に沿った方法で復号する場合のコマンドは次になります。

$ openssl enc -d -aes-256-cbc -pass pass:xyz -in enc.dat

これを 2. に沿った方法で扱う場合、鍵・IVを調べ、その上でオプションを指定しなければなりません。
※-K,-ivオプションが相当します。指定する値は、暗号化時に割り当てられたsaltによっても変わることに注意してください。
※tailしているのは、先頭にあるsalt情報を取り除くためです。

$ openssl enc -P -d -aes-256-cbc -pass pass:xyz -in enc.dat # 鍵・IVの調査 salt=82A583025BF446D0 key=D2F94536C4F265D45FA439982476D5B877ED0D209D6627F41C326CDF07550FCC iv =B7B74563864C3A86FFCDAF0DB97B069A $ tail -c +17 enc.dat | openssl enc -d -aes-256-cbc -K D2F94536C4F265D45FA439982476D5B877ED0D209D6627F41C326CDF07550FCC -iv B7B74563864C3A86FFCDAF0DB97B069A

で、これに対応するPHPでの関数の使い方は次のようになります。
$encが enc.dat の内容をそのまま保持しているものとします。

$keyhex="D2F94536C4F265D45FA439982476D5B877ED0D209D6627F41C326CDF07550FCC"; $ivhex ="B7B74563864C3A86FFCDAF0DB97B069A"; echo openssl_decrypt(substr($enc,16),"aes-256-cbc",hex2bin($keyhex),OPENSSL_RAW_DATA,hex2bin($ivhex));

※追記
パスワード・salt→鍵・IVを知る方法はopenssl独自ですが、一応次の方法で真似ることはできます。ただ、指定するオプションによって細部は変わってきます。今回はデフォルト ( -md 未指定=sha256, pbkdf2 未使用 ) に対応した方法です。

$pass="xyz"; $salt=substr($enc,8,8); $key=openssl_digest($pass.$salt,"sha256",true); $iv=substr(openssl_digest($key.$pass.$salt,"sha256",true),0,16); echo openssl_decrypt(substr($enc,16),"aes-256-cbc",$key,OPENSSL_RAW_DATA,$iv);

投稿2021/10/26 10:18

編集2021/10/26 11:16
angel_p_57

総合スコア1681

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takemoto_piano

2021/10/28 01:11

ご丁寧に詳細な解説までしていただき本当にありがとうございます。 暗号化したのが自分ではないため、暗号方式aes-256-cbcと暗号鍵“xxx”を用いて暗号化した後base64でエンコードした以外の情報がありません。また、IVに関しての情報もなく、おそらく「パスワードを与えてsalt(ツールがランダム生成)を加えて変換して鍵・IVを生成 」したものであると思われます。ここで、暗号化で与えられたはずのパスワードと、暗号鍵”xxx”は違うものなのでしょうか?暗号鍵”xxx”はパスワードを変換して生成された鍵なのでしょうか? 1.の手順だと仮定して、PHPでのではなくOpenSSLによる復号を試みました。 OpenSSLをインストールしcmdから起動して以下のコマンドで実行しました。 $ openssl enc -aes-256-cbc -d -pass pass:xxx -in opensslCrypto.txt opensslCrypto.txtにはエンコードされた文が入っています。 実行結果として「bad magic number」と出てしまいました。 Javaで暗号化した文章をOpenSSLで復号化しようとすると出てしまうといった話も見かけたのですが、原因と対策が全く分からず難航しています。どうしたらよいのでしょうか? 情報が少なく申し訳ありません。ご回答いただけたら幸いです。
angel_p_57

2021/10/28 10:56

> ここで、暗号化で与えられたはずのパスワードと、暗号鍵”xxx”は違うものなのでしょうか?暗号鍵”xxx”はパスワードを変換して生成された鍵なのでしょうか? それはなんとも言えません。が、aes-256-cbc における「鍵」は32バイト(256ビット)のランダムデータなので、それに合っていなければ "xxx" は鍵ではないと思います。 > 実行結果として「bad magic number」と出てしまいました。 base64エンコードされている場合は、-a オプションを併用するか、先に base64 -d でデコードしてから復号を試してください。 それで、opensslコマンドでパスワードを指定してbase64エンコード無しで暗号化した場合は、Salted__+8文字のランダムバイトのsaltが暗号データの先頭に来ます。 このsalt部分がないと、パスワードから鍵・IVの計算ができません。 なので、xxd opensslCrypto.txt や base64 -d opensslCrypto.txt | xxd で見てsalt部分が先頭にないようなら、情報不十分で処理できない、ということになります。
takemoto_piano

2021/10/28 14:03 編集

ご丁寧にご返答いただき本当にありがとうございます。 >base64エンコードされている場合は、-a オプションを併用するか、先に base64 -d でデコードしてから復号を試してください いずれも試してみましたがうまくいきませんでした。ダメもとでパスワードのデコードの有無、本文のデコードの有無も組み合わせてすべて試しましたがbad magic numberと出てしまいました。 >opensslコマンドでパスワードを指定してbase64エンコード無しで暗号化した場合は、Salted__+8文字のランダムバイトのsaltが暗号データの先頭に来ます。 このsalt部分がないと、パスワードから鍵・IVの計算ができません。 なので、xxd opensslCrypto.txt や base64 -d opensslCrypto.txt | xxd で見てsalt部分が先頭にないようなら、情報不十分で処理できない、ということになります。 base64エンコードなしで暗号化されている暗号文の先頭部のSaltのバイト数はどのように決まるのでしょうか?またどの部分がSaltであるかを見分ける方法はありますか? 今回base64エンコードで暗号化されたん文章ですが、この場合は暗号文の先頭にSaltはないのでしょうか?或いは見つけることができないのでしょうか? 何度も申し訳ありません。よろしくお願いいたします。
angel_p_57

2021/10/28 14:18

> base64エンコードなしで暗号化されている暗号文の先頭部のSaltのバイト数はどのように決まるのでしょうか?またどの部分がSaltであるかを見分ける方法はありますか? 本件の話題を先日記事にしてます。「鍵データの正体」の章をご覧ください。salt部分のサンプルも載せています。 https://qiita.com/angel_p_57/items/bc50c5cfbb0276e07707#%E9%8D%B5%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E6%AD%A3%E4%BD%93 なので、暗号データ ( base64エンコードされているなら、デコードしたもの ) が、上記サンプルのようになっていなければ、復号するための情報が足りないということになります。
takemoto_piano

2021/10/28 14:46

早速のご返答ありがとうございます。 暗号文をデコードしてみたところsalt__に続く文字列が現れました! ですが、文字化けしたような表現になってしまっておりうまくデクリプトできませんでした。 文字化けしてしまっているSaltが出てしまうのは何が原因なのでしょうか?
takemoto_piano

2021/10/28 14:48

度々申し訳ありません -Pを用いたらSalt値が出てきたのでもう少し試してみます。
takemoto_piano

2021/10/28 15:09

上記のとおり暗号文をbase64でデコードした文章にSalt__から続く文字列が現れましたが、文字化けしている状態でした。 このデコードした文章から-PでSalt値とkey,IVを引っ張り出して復号しようとしましたが、やはり文字化けした意味不明な文章が現れました。(salt,IV,keyいずれも16進数で表されており、saltは16bitでした) また、デコード前の暗号文で-Pを用いて試しましたがまた意味不明な文字化けした文章が現れました。 さらに、文字化けした最後に(bad decrypt)と言われてしまい詰んでしまいました。 デコード後は文字化けした文字列が現れるのは一般的でしょうか?
angel_p_57

2021/10/28 16:27

> デコード後は文字化けした文字列が現れるのは一般的でしょうか? それは一般的です。( なので記事では xxd による16進ダンプで内容を見ています ) > (bad decrypt)と言われてしまい詰んでしまいました。 暗号データは、元のデータのデータ長に依存する情報を含んでいますので、復号してできたデータで長さが合わないようだと大抵は bad decrypt に引っかかります。これは、パスワードが違うか、あるいはパスワード→鍵・IVの生成方式の違いで鍵・IVが正しくない場合に該当します。 まずは、openssl enc -d -aes-256-cbc -pass pass:パスワード -in デコードしたファイル で bad decrypt が出ずに復号できるところの確認ですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問