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

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

ただいまの
回答率

88.59%

JavaScript(以下JS) と PHP での暗号化・復号について質問です.

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 3,840

Pccla

score 35

JavaScript(以下JS) と PHP での暗号化・復号について質問です.

JSでの暗号化には CryptoJS, 
PHP側での復号にはopenssl_decryptを使います.

以下のようにJSで暗号したのですが、PHPで復号できず困っています.
セキュリティ的に安全であれば他の方法でも構いませんので、どこが原因かご教示いただけると幸いです!!

JS側での暗号化

        // 暗号化用パス
        var secretPass = CryptoJS.enc.Utf8.parse('pass');
        // ランダム値生成してsaltを設定
        var salt = CryptoJS.lib.WordArray.random(128 / 16);
        // 暗号化で使うキーを設定(先ほど作ったsecretPassとsaltを使用)
        var key = CryptoJS.PBKDF2(secretPass, salt, {keySize: 128 / 16, iterations: 1000 });
        //初期化ベクトル
        var iv = CryptoJS.lib.WordArray.random(128 / 16);
        //暗号化オプション(IV:初期化ベクトル, CBCモード, パディングモード:PKCS7)
        var options = {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7};
        //暗号化内容のエンコーディングは「UTF-8」
        var baseText = CryptoJS.enc.Utf8.parse('IWantToDecryptThisString');

        //暗号化
        var encrypted = CryptoJS.AES.encrypt(baseText, key, options);

PHPでは復号のメソッドを作り、openssl_decrypt関数を実行した時点での
ログを出力したところ、返り値は空っぽでした.
以下PHPの復号メソッドで、引数自体は渡ってきてます.

$encData : yWvjtqSQKl8kzJwgeri%2BtA%3D%3D $iv : 49bb573d407b4b64d20445f0c4b20279 $key : bcbc43c15b482e4579529039ecbd32345b2f462f796f904a0eceffed93d5186da7f609c40a303f497a68615e14474b5f73f7f66bb80df298d5918fc1a9120eec

$encData : bnqTjLlAWs0aAZZkX7kZnw==
$iv : 682efaee374ec613
$key : 5b4076f60e3fb3a0649a5fcf1fb71e551f634a5017b6d529cffc65c06eb34724

    public function decData( $encData, $iv, $key ){
        $decData = '';
        // 復号に使うメソッド
        $method   = 'AES-128-CBC';
        // 復号に使うオプション
        $options = 'OPENSSL_RAW_DATA';

        // 復号
        //$decData = openssl_decrypt(pack("H*", $encData), $method, $key, $options, $iv);
        $urlDecodeEncData = urldecode($encData);
        $decData = openssl_decrypt($urlDecodeEncData, $method, $ky, $options, $iv);

$this->log('復号処理結果', LOG_INFO);
// 以下のログは空っぽでした
$this->log($decData, LOG_INFO);

        return $decData;
    }
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+4

JS側で生成するivの長さが間違っているようです
また、php側での複合化に使うメソッドが違うようです

下記で動作サンプルになります

js

// 暗号化用パス
var secretPass = CryptoJS.enc.Utf8.parse('pass');

// ランダム値生成してsaltを設定
var salt = CryptoJS.lib.WordArray.random(128 / 16);

// 暗号化で使うキーを設定(先ほど作ったsecretPassとsaltを使用)
var key = CryptoJS.PBKDF2(secretPass, salt, {keySize: 128 / 16, iterations: 1000 });

//初期化ベクトル
var iv = CryptoJS.lib.WordArray.random(128 / 8);

//暗号化オプション(IV:初期化ベクトル, CBCモード, パディングモード:PKCS7)
var options = {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7};

//暗号化内容のエンコーディングは「UTF-8」
var baseText = CryptoJS.enc.Utf8.parse('IWantToDecryptThisString');

//暗号化
var encrypted = CryptoJS.AES.encrypt(baseText, key, options);

// UA2EX1WGut9X0r3KyGvja0rJoTLGGuqt548VqOC2uS4=
console.log(CryptoJS.enc.Base64.stringify(encrypted.ciphertext))

// 448e82b5ba5ce418b1e89f720af3e0680c8b6958f3050632849dfc028fa8784e
console.log(CryptoJS.enc.Hex.stringify(key))

// 6f0d81e8371d8befb39054ae2f969f36
console.log(CryptoJS.enc.Hex.stringify(iv))

php

<?php

function decData( $encData, $iv, $key ) {
    $encData = base64_decode($encData);
    $iv = hex2bin($iv);
    $key = hex2bin($key);

    // 復号に使うメソッド
    $method   = 'AES-256-CBC';

    // 復号に使うオプション
    $options = OPENSSL_RAW_DATA;

    $decData = openssl_decrypt($encData, $method, $key, OPENSSL_RAW_DATA, $iv);

    return $decData;
}

$encData = "UA2EX1WGut9X0r3KyGvja0rJoTLGGuqt548VqOC2uS4=";
$key = "448e82b5ba5ce418b1e89f720af3e0680c8b6958f3050632849dfc028fa8784e";
$iv = "6f0d81e8371d8befb39054ae2f969f36";

var_dump(decData( $encData, $iv, $key ));

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/02/14 07:44

    コメントありがとうございます。

    > ・関数のドキュメントを読む

    ここがうまくいかなかったんですよね^^;

    CryptoJS.PBKDF2 のデフォルトの設定が確認ができず、迷走してしまいました。
    修正前の回答が大変参考になりました。

    学習のため、もう少し追いかけてみます。

    キャンセル

  • 2018/02/14 12:13

    ありがとうございます!ご教示いただいた通り、動かしたところ暗号化・復号できました!!
    ただ、こちらのPHPのバージョンが5.3とかなり古い状態なので、hex2binが使えず、代わりにpack('H*',)を使いました。

    キャンセル

  • 2018/02/14 12:16

    先にご回答いただいたお二方のご意見も大変勉強になりました!
    私のググる力などが弱く、もの凄く困っているところを助けていただき本当にありがとうございました!!
    感謝ですm(_ _)m
    このあたりの分野は初めてだったので、もう少しググったりして理解度を深めようと思います。

    キャンセル

0

$options = 'OPENSSL_RAW_DATA';

$options = OPENSSL_RAW_DATA;

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/02/13 10:05

    返答が遅くなり申し訳ございません。
    シングルクオテーションを外してみたんですが、返り値は空でした。

    キャンセル

0

デバッグとしては 2 手順を試してください。

1,$decData = openssl_decrypt(pack("H*", $encData), $method, $key, $params['options'], $iv);の各変数に、投入されているべきデータを実際に投入してみて意図したモノが返却されているか?

2,$decData = openssl_decrypt(pack("H*", $encData), $method, $key, $params['options'], $iv);時点でのそれぞれの変数が意図したものになっているのか?

1 が変であれば、openssl_decrypt の使用方法をもう一度確認します。
2 が変であれば、変数を追うことで、問題箇所が特定できます。

デバッグの環境さえ整えてあれば、それほど難しい切り分けではないと思います。

追記
本回答は、「PHP での暗号化・復号について」の回答ではなく、ただのデバッグに関しての記述です。

<?php
$encData = 'yWvjtqSQKl8kzJwgeri%2BtA%3D%3D';
$iv = '49bb573d407b4b64d20445f0c4b20279';
$key = 'bcbc43c15b482e4579529039ecbd32345b2f462f796f904a0eceffed93d5186da7f609c40a303f497a68615e14474b5f73f7f66bb80df298d5918fc1a9120eec';
$decData = '';
// 復号に使うメソッド
$method   = 'AES-128-CBC';
// 復号に使うオプション
$options = OPENSSL_RAW_DATA;
// 復号
$decData = openssl_decrypt(pack("H*", $encData), $method, $key, $params['options'], $iv);
PHP Warning:  pack(): Type H: illegal hex digit y in /workspace/Main.php on line 11
PHP Warning:  pack(): Type H: illegal hex digit W in /workspace/Main.php on line 11
PHP Warning:  pack(): Type H: illegal hex digit v in /workspace/Main.php on line 11
…
PHP Warning:  pack(): Type H: illegal hex digit % in /workspace/Main.php on line 11
PHP Notice:  Undefined variable: params in /workspace/Main.php on line 11
PHP Warning:  openssl_decrypt(): IV passed is 32 bytes long which is longer than the 16 expected by selected cipher, truncating in /workspace/Main.php on line 11


$encData がおかしいんじゃないですか?

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/02/13 19:58

    返り値は相変わらず空で、今度はエラーもでないので、困ってます...

    キャンセル

  • 2018/02/14 07:55

    openssl_decrypt の返り値が false になるので、復号に失敗しています。
    与える引数がおかしいということになるので、中で使っている変数を見直す必要があります。

    で、少し追いかけてみたのですが、そもそもの処理としておかしな点が多くありました。根本的に見直してみないと解決しないようです。

    具体的には以下の見直しが必要かと
    ・暗号化手順の確認
    ・復号手順の確認
    ・各種パラメータの作成方法の確認
    ・使用関数の挙動確認(デフォルト設定内容の確認を含む)

    言語を渡るので、使用関数の設定内容を合わせることが必要になります。

    esuzuki さんの回答を、修正前の履歴も含めて追っかけてみると、前に進めると思います。

    キャンセル

  • 2018/02/14 16:31

    JS側でのエンコードの仕方、ivの長さ、
    PHP側でデコードの仕方と復号メソッドなど色々間違っておりました。
    ご教示いただきありがとうございました!

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る