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

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

ただいまの
回答率

90.52%

  • PHP

    23487questions

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

php暗号化時の一意性について

受付中

回答 4

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 2,616

enigumalu

score 172

php暗号化時の一意性について
phpのopenssl_encryptを利用した場合
暗号化する前の文字が一意を保たれていた場合、暗号化後も一意が保たれるでしょうか。(パスワードは固定です)

$iv = '1234567890123456';
var_dump(openssl_encrypt('1486601281','AES-256-CBC','aaatest',0,$iv));
var_dump(unpack("H*", openssl_encrypt('1486601281','AES-256-CBC','aaatest',0,$iv)));
結果
string(24) "V3zbf8fVlSc32J/+76vpNg=="
array(1) {
 [1]=>
 string(48) "56337a62663866566c536333324a2f2b373676704e673d3d"
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • ikedas

    2017/02/08 19:35

    自分で試してみましたか。試したコードとその結果を提示していただけませんか。

    キャンセル

  • ockeghem

    2017/02/08 21:12

    初期化ベクトルはどうしていますか?

    キャンセル

  • enigumalu

    2017/02/09 10:04

    すいません初期化ベクトルに関して考慮が抜けていましたが、固定文言を渡すようにしています

    キャンセル

  • ikedas

    2017/02/09 10:11

    自分で試してみた結果を提示して下さいませんか。

    キャンセル

回答 4

+2

質問者さんの提示したコードでは暗号方式にAES-256-CBCが指定されていますから、暗号化のたびにランダムな初期化ベクタ (IV) を指定しなければなりません。ですから、平文が一意であっても暗号文は一意になりません。

以下、説明です。

  • 初期化ベクタ (IV) やソルトを使わない暗号方式では、平文と暗号文が一対一に対応します。ブロック暗号では、ECBモードの場合はIVを使いません。
    しかし、このような暗号方式はもはや用いるべきではありません

  • 初期化ベクタ (IV) やナンス (nonce) を使う暗号方式は、IVやナンスを暗号化の度に変えるという正しい運用をするかぎり、同じ平文が同じ暗号文になることはほぼありません。ブロック暗号では、ECB以外のモードではIVを用いる (CBC、CFB、OFB等) かナンスを用いる (CTR等) かです。
    そして、IVやナンスに固定した値を用いるべきではありません

IVを使わない暗号方式を使うことも、IVを固定して使うことも、するべきでない理由は同じです。そのようなものは、現在では十分な強度のある暗号方式とみなされていないからです。

「でも、IVを固定すれば一意になるんでしょう。ならそういう使いかたをしたっていいじゃないか」と思うかもしれません。しかし、暗号方式の設計で想定されている以外の運用をすれば、暗号化の強度は全く保証できなくなります。暗号化しているつもりで安心していると、すべて誰かに解読されてしまっているかもしれないのです。これほど危険なことはありません。


参考文献


ところで、質問者さんのやりたいことが何なのか、いまひとつわかりません。

一意な文字列を作りたいのであれば、規則的に変化するもの (連番など) でいいはずです。規則性のない文字列にしたいのであれば、乱数を使うしかありません。両立は無理です。

また、やりたいことがわからないので憶測ですが、文字列を予測困難にする――次に生成される文字列を隠す――必要があるのかどうかも、再考すべきなのかもしれません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

復号できるデータは、暗号化する前のデータと一対一で結びつきます。

openssl_encrypt は復号可能な暗号アルゴリズムを使用するので、暗号化後の文字列は暗号化した文字列の中で一意のものとなります。

追記
別の場所で、初期化ベクトルのこと考えてないんじゃないの?と指摘を受けました。
確かに、初期化ベクトルが異なれば、暗号化後の文字列が被る可能性がありますね^^;
初期化ベクトルと暗号化後の文字列をセットとして考えた時、一意性が確保されます。と補完させていただきます。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/02/09 10:03

    初期化ベクトルivも固定値を渡すようにしています。
    $iv = '1234567890123456';
    var_dump(openssl_encrypt('1486601281','AES-256-CBC','aaatest',0,$iv));
    var_dump(unpack("H*", openssl_encrypt('1486601281','AES-256-CBC','aaatest',0,$iv)));
    記号をなくすために最終的にunpackしているのですがこれだとさすがに一意にはならないですよね

    キャンセル

  • 2017/02/09 13:52

    ikedas さんも指摘していますが、何をやりたいのかよく分かりません。
    そもそも何をやりたいのか分かれば、適切な解なり検討方法なりのアドバイスが貰えると思います。

    もう一度整理されては?

    キャンセル

+1

既に書かれていますが、復号可能である以上、元の平文と暗号文は1対1に対応します。複数の平文が同じ暗号文になることはありません。

ですが、そうすると、「同じ文面では同じ暗号文が出てくる」ので、特に先頭に定型文があると「あ、定型的な文章を送っているな」と類推されてしまう危険性があります。
※先頭のブロックが同一だと、暗号文も同一でスタートします

そこで初期化ベクトルという「先頭にランダムな1ブロックを加える」ことにより、「同じ文面でも異なる暗号文を出す」ようになっているわけです。
※ゆえに初期化ベクトルのサイズは暗号化時のブロックサイズと一致していなければならない
このため復号時には暗号化で使用した初期化ベクトルも知っている必要があります。

平文(あるいは暗号文)と初期化ベクトルの組が一意であれば、暗号化もしくは復号した結果も一意になります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

質問の意図(やりたいこと)がうまく捉えられているか分かりませんが

  • 相異なる平文から1対1で対応する(=相異なる)ランダムに見える値を得たい。
  • 変換後の値から平文に戻す必要はない。

ならハッシュを使えばよいのでは?
ハッシュ関数によっては1対1にならない可能性もありますが(詳しくは「衝突耐性」で調べてください)

また、以下は自分の疑問に対する覚書なので無視してくださって結構です。

問:暗号時にIVをランダムで生成した場合、復号側ではIVはどうやって知るのか?

答(opensslでの実装)
・ソルト+暗号データを渡す。ソルトは単なるランダム値なので見えてもよい。
・(暗号鍵と)IVはパスワードとソルトからハッシュで生成する。

salt   = 暗号側でランダム生成。復号側は受け取って利用する。
暗号鍵 = MD5(password + salt)
IV     = MD5(暗号鍵 + password + salt)


参考:Opensslの暗号鍵とIVの生成アルゴリズム

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • PHP

    23487questions

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