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

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

ただいまの
回答率

90.12%

PHPのCryPt関数でハッシュ化した値を復号したい

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 5,791

前提・実現したいこと

PHPのCryPt関数でハッシュ化した値を、復号したい

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

PHPのCryPt関数でハッシュ化した値を復号したいです。

crypt($str, SALT);を使ってハッシュ値を生成しています。
SALTはdefineで定義した固定文字列です。

結果、13桁のハッシュ値が生成されています。このハッシュ値とSALTを元に
元の$strを復号したいのですがうまくできません。

該当のソースコード

//SALT
define(SALT , "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
//ハッシュ化処理
$str_hash = crypt($str, SALT);
//復号化用のプログラム

<?php
//ハッシュ化された値(例)
$str_hash = "ABCDEFGHIJKLM";(サンプル、実際には英数字の混ざった13桁のハッシュ値)

//SALT
$salt = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

$str_encrypt = new StringEncrypt();

//暗号化
$decrypted = $str_encrypt->decrypt($encrypted, $pass); 
echo $decrypted ."\n";

?>


<?php
class StringEncrypt
{
    private $td;
    private $iv_size;
    private $algorithm;
    private $mode;
    private $init = false;

    function __construct($algorithm="blowfish", $mode="ecb"){
        $this->algorithm = $algorithm;
        $this->mode = $mode;
        $this->td = mcrypt_module_open($this->algorithm, '', $this->mode, '');
        $this->iv_size  = mcrypt_enc_get_iv_size($this->td);
    }

    function __destruct(){
        if($this->init) mcrypt_generic_deinit($this->td);
        mcrypt_module_close($this->td);
    }

    private function init($pass, $iv=null){
        if(is_null($iv)){
            $iv = mcrypt_create_iv($this->iv_size, MCRYPT_DEV_RANDOM);
        } else {
            $iv = base64_decode($iv);
        }

        if($this->iv_size !== strlen($iv)){
            throw new Exception("Incorrect IV size.");
        };

        $key = substr( md5($pass), 0, mcrypt_enc_get_key_size($this->td));
        mcrypt_generic_init($this->td, $key, $iv);
        $this->init = true;
    }

    public function encrypt($str, $pass, $iv=null){
        $iv = $this->init($pass, $iv);
        $encrypted = mcrypt_generic($this->td, $str);
        return base64_encode($encrypted);
    }

    public function decrypt($str, $pass, $iv=null){
        echo $str;
        $iv = $this->init($pass, $iv);
        //$str = base64_decode($str);
        $decrypted = mdecrypt_generic($this->td, $str);
        echo $decrypted;
        return rtrim($decrypted);
    }

    public function create_iv(){
        $iv = mcrypt_create_iv($this->iv_size, MCRYPT_DEV_RANDOM);
        return base64_encode($iv);
    }
}

試したこと

コマンドプロンプトで上記のプログラムで復号化しようと思いましたが、
出力値が文字化けしてしまい想定した値を得ることができなかった。

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

PHP 5.2.0(誤)
PHP 5.4.28(正)

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

PHPマニュアルにも明記してありますが、

注意: 復号するための関数はありません。 crypt() が使用しているのは単方向アルゴリズムだからです。

crypt()関数は、パスワードのように、復元できないことに価値がある場面で使う関数です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/24 09:30

    ありがとうございます。crypt()関数は、復元できないという点、理解できました。

    キャンセル

+2

そもそも「何故復号が必要なのか」についてもっと洗いだした方がいいかと思います.名前や住所を暗号化する場合は復号が必要なのも頷けますが,パスワードは復号できてはいけません.また,名前や住所であっても本当に暗号化する必要があるのかについてはよく検討してください.

PHP5.5以降からはcryptよりも使いやすいpassword_hashの使用が推奨されているのでそちらで
と,言いたいところですが太古のPHP5.2を使われているようですね…
何かしら事情があるのかもしれませんが,可能な場合はアップデートを推奨します.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/23 10:40

    というか5.2.xの最新版じゃなくて5.2.0なので脆弱性あるんじゃないですかね.めちゃくちゃ危ないと思いますよ.バグもたくさんありますし.

    キャンセル

  • 2016/06/23 10:45

    5.2.0だと脆弱性が152個ありますね.危険な順に並べてみました.

    https://www.cvedetails.com/vulnerability-list.php?vendor_id=74&product_id=128&version_id=38979&page=1&order=3

    キャンセル

  • 2016/06/24 09:37

    ありがとうございます。cryptについて理解できました。
    バージョンの記載誤りがありました。PHP 5.4.28でした。

    ただ、PHP 5.4.28もだいぶ古いのでアップデートを検討しています。アドバイスありがとうございました。

    キャンセル

+1

ハッシュについて誤解されているように思います。

ハッシュはハッシュから元の値に戻せない必要があります。
また、複数の異なる値が同じハッシュになる場合もあります。

元に戻す必要があるのであれば、
ハッシュではなく可逆暗号化を行う必要があります。
例えばPHPマニュアル mcrypt_generic()等を使います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/23 10:12 編集

    コメントに誤解があったので削除します。

    キャンセル

  • 2016/06/23 10:15 編集

    class StringEncryptでは暗号化メソッドencrypt()が実装されているようなので、
    何か理由が無い限りは暗号化の際はこのクラスのencrypt()を使用するのがベストかと思います。

    キャンセル

  • 2016/06/24 09:31

    回答ありがとうございます。
    crypt()関数は、復元できないという点、理解できました。復号化が必要な場合は、mcrypt_generic()などの可逆暗号化を使うようにします。

    キャンセル

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

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる