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

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

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

Deviseとは、Ruby-on-Railsの認証機能を追加するプラグインです。

セキュリティー

このタグは、コンピューターシステムの安全性やデータの機密性に関連したトピックの為に使われます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

暗号化

ネットワークを通じてデジタルデータをやり取りする際に、第三者に解読されることのないよう、アルゴリズムを用いてデータを変換すること。

Q&A

解決済

7回答

10485閲覧

なぜdevise等の認証(パスワード)は非可逆なハッシュ化をしているのにログインが出来るのかが分からない

widget11

総合スコア221

Devise

Deviseとは、Ruby-on-Railsの認証機能を追加するプラグインです。

セキュリティー

このタグは、コンピューターシステムの安全性やデータの機密性に関連したトピックの為に使われます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

暗号化

ネットワークを通じてデジタルデータをやり取りする際に、第三者に解読されることのないよう、アルゴリズムを用いてデータを変換すること。

4グッド

17クリップ

投稿2019/11/13 09:41

例えばdevise等の認証系ライブラリではパスワードを登録した際にその文字列がハッシュ化されDBに格納していると思います。
例えばログインする際、暗号化であれば例えばBASE64などは一定の法則があって復号化が可能で、DBに入っている文字列を復号化し入力した値を照らし合わせるということが出来ると思うのですが、非可逆なハッシュ文字列を用いて認証を出来る意味が良く分かりません。
同じ文字列をハッシュ化しても同じハッシュ化された文字列にはなりませんよね?
よろしくお願い致します。

naotiki, hihijiji, GenbuHase, GO9👍を押しています

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

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

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

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

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

guest

回答7

0

ベストアンサー

[追記]
一般的なユーザー登録と認証の概要だけの説明です。
セキュリティめっちゃ大事なので、概要をつかめたら是非他の人のアンサーを読んで考えてみたり、
devise本体の実装も読んでみてください。

※前提としてハッシュ関数は一方向の関数であり、同じ文字列を同じアルゴリズムでハッシュ化すると必ず同じハッシュ値が得られます。

ステップ①:ユーザー登録時

仮にパスワードにabcという文字列を指定するとします。

abcという文字列をSHA256でハッシュ化するとBA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD
という不可逆な文字列になるので、これをDBに登録しておきます。

ステップ②:ログイン時

ユーザーはログインする時にパスワードにabcという文字列を指定します。

プログラムはabcという文字列を同じアルゴリズム、この場合はSHA256でハッシュ化して、BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015ADという文字列を作り、DBに登録されている文字列BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015ADと比較します。

この場合2つの文字列は一致しているので、プログラムは「正しいパスワードが入力された」とみなすことができます。

DBにはハッシュ関数でハッシュ化された不可逆な情報しか登録されていないので、万が一漏洩した場合でも、本当のパスワードabcを知ることができません。

補足

ハッシュ化された値は不可逆ですが、SHA256でハッシュ化するとabcBA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015ADという値になるよねということは周知の事実です。

世の中にはいろんな人がいて、入力値とハッシュ値のペアのデータベースを作成している人がいます。
そういったデータベースにはレインボーテーブルという名前がついています。
このデータベースを参照すると、ハッシュ値から元の入力値を調べることが可能だったりするので、ソルトという方法を使ってレインボーテーブルを参照する攻撃を回避します。

ソルトもよければ調べてみて下さい。

投稿2019/11/13 09:56

編集2019/11/19 15:04
wuzzy

総合スコア152

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

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

widget11

2019/11/14 09:21

皆さんがおっしゃっているようにハッシュ化は毎度違う値になると勘違いしていました。 しかしレインボーテーブルという言葉初めて聞いたのですがめちゃくちゃ面白いです! ありがとうございます!
guest

0

BAが決まってますが、凄く勘違いしていそうですし、セキュリティ上問題がある方法だけが示され続けるのも問題と思いますので…。

パスワードを登録した際にその文字列がハッシュ化されDBに格納していると思います。

質問においてこの部分が間違っています。完全に間違っているわけでは無く、正確にはこうです。

「パスワードを登録した際にその文字列とランダムに生成するソルトを組み合わせたものがハッシュ化されソルトと一緒にDBに格納している」

ソルトを使用しない方式(LDAP passwordの{MD5}と{SHA}とかわざとそうしている実装はある)や、バグでソルトが常に同じになる(実際にそういう製品があった)場合は、レインボーテーブル攻撃に脆弱になるといったセキュリティ上問題があるため、使用すべきではありません。deviseを含めた認証ライブラリの実装ではソルトは必ず使用しています。これらの実装では、登録時は、例え同じパスワードであっても、毎回ランダムに生成された異なるソルトが使用され、結果毎回異なるハッシュ値が生成され、DBにはソルトとハッシュ値の両方が保存されています。認証時は、パスワードとDBにあるソルトからハッシュ値を生成し、DB上のハッシュ値と比較するという方法を取っています。

投稿2019/11/15 23:50

raccy

総合スコア21735

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

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

dameo

2019/11/16 00:35

BAにもレインボーテーブルとソルトの記述はあり、誤解と取れる質問者の記述も見当たりませんよ。 啓蒙は大事ですが、概念の理解と実運用の際の大仰な注意は必ずしも同時にしなくてもいいと思います。それこそ誤解に繋がってしまうので。
raccy

2019/11/16 03:04

回答は質問者だけが見ているわけではありませんので、質問者が理解できているかどうかよりも、回答そのものが他の人に誤解無く理解できるかどうかを私は重視します。 次に、セキュリティに関わる話は、それを説明するのにどんなに複雑なことであろうと、軽視してはいけないと私は考えています。大げさと言いますが、大げさにしてもまったく足りないぐらいと思っています。 dameoさんと私とでは回答に対する考え方や態度そのものが異なるようですので、そのことについて議論はしません。ただ、私は上の考えで、今後も回答もするし、コメントもすると言うだけです。
dameo

2019/11/16 03:11

誤解のないということであれば、パスワードとソルトに分離せずに、元データとか言うべきだし、特定のアルゴリズムに必要な値はそれだけではないかもしれません。どこまで行ったら正確か、ということは個人的に主観でしかないと思いますよ。回答に対する考え方も態度も同じつもりですが、これ以上の議論は無駄かもしれませんね。
H40831

2019/11/19 00:14

横から恐縮です。 Teratailのメルマガから飛んできた現在勉強中の初心者ですが、 個人的にはこちらの解説のおかげですごくわかりやすかったですし、おかげで自分も同様の誤解をしていたのですが解決しました。 「概念の理解と実運用の際の大仰な注意は必ずしも同時にしなくてもいい」ということですが、初心者としては、同時には説明されなくていいけど、その回答(記事)上のどこかでは解説してほしいです。 遠く離れた場所で説明されても、それとこれが結びつくかどうかの確信が持てません。 なんだか散々な言われようだったので一応フォローさせていただきました。 助かりました。
dameo

2019/11/19 01:25

+αを理解する余裕のある人と、+αがあることによって元の理解に混乱を来す人がいるってことです。 そもそも余裕のある人は自分で調べられるので、実運用の際にも間違えることはあまりありません。 あと結びつく/つかないではなく、要件が全く違うので、実運用(設計)では再度現実に即した真剣なリスクの検討が必要なだけですよ。 あと厳しいことは言ってないというか、そもそも責めてるわけでありません… 何を誤解してたのか知りませんが、解決してよかったですね。
退会済みユーザー

退会済みユーザー

2019/11/21 23:47

この回答、なんでストレッチングへの言及がないのですか? raccy さんの回答としては違和感があります。
raccy

2019/11/22 09:57

te2jiさん いや、誤解していそうな所だけ回答したからです。 安全性について詳しく話をするとストレッチングだけでは無く、ハッシュアルゴリズム自体の安全性(MD5のような脆弱性が見つかっているとか、そもそも結果の空間が小さいとか)、ハッシュアルゴリズム自体のコスト(特にハードウェアで高速なものが作れるかどうか)、ソルト・パスワード・前ラウンドの結果を次ラウンドでどのように組み合わせるのかとか、話したらきりが無いですし、書籍一冊とは言わないまでも、論文一つにはなりそうですので。 ストレッチングの回数、いわゆる反復回数やコストが自由に選択できるようなメジャーな実装って、bcryptぐらいでは無いでしょうか。でも、bcrypt($2y$のやつ)だとちゃんとコストも保存されるから、言及した方が良かったかなとは今更ながら思っていたりもします。
退会済みユーザー

退会済みユーザー

2019/11/22 20:59

コメントありがとうございます。 記述意図、理解しました。聞いてみてよかった。 余談) php の PASSWORD_ARGON2I はひどい出力になってましたw bcrypt の出力はきれいですね。
guest

0

同じ文字列をハッシュ化しても同じハッシュ化された文字列にはなりませんよね?

この勘違いが間違いのもとだと思います。

同じ文字列、同じハッシュ関数(、同じソルト文字列)の場合は、ハッシュ値は同じです。

そもそも、ハッシュ関数は大きなデータ(ファイル等)の同一性検査に使われ始めたものです。
ハッシュ値が同じことを以て、元の大きなデータ同士を直接コンペアすることなく、同一性を確認します。
「同じデータなら同じハッシュ値」がハッシュの一番重要な性質です。

投稿2019/11/13 13:35

otn

総合スコア84555

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

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

0

厳密に言えばハッシュは暗号ではありません。
暗号は「復号できなければならない」ので、一方向・多対一変換であるハッシュは暗号たり得ません。

ハッシュは「与えられたデータを、何らかの法則に従って計算した結果」であって、

  • 同じ入力だと同じハッシュ値が返ってくる
  • 違う入力に対しては基本的には別のハッシュ値が返ってくる
  • 違う入力に対して、同一のハッシュ値が返ることはある(ハッシュの衝突)

特性を持っています。
そこで、データそのものを比べるのではなく、データから計算したハッシュ値を比べることで、「ほとんどの場合」入力の同一性をチェックすることに使える、というものです。
※加えてハッシュ値計算の手間はかかるものの、データそのものを全部比べるより資源を必要としないという利点があります

投稿2019/11/14 01:23

tacsheaven

総合スコア13703

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

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

maisumakun

2019/11/14 01:32

> ※加えてハッシュ値計算の手間はかかるものの、データそのものを全部比べるより資源を必要としないという利点があります パスワードへ適用する場合、そのままでは総当たり攻撃に対して弱くなってしまうので、わざとハッシュ化自体に(ログイン時の1回ならどうということはない程度には)コストの掛かる手法を使って、攻撃コストを引き上げる「ストレッチング」が行われています。
guest

0

例えばログインする際、暗号化であれば例えばBASE64などは一定の法則があって復号化が可能で、DBに入っている文字列を復号化し入力した値を照らし合わせるということが出来る

出来るといえば出来ますが、復号はしないのです。
同じようにハッシュ値を計算してそれが一致することを確認するだけです。
ハッシュ値にしているのは、単に平文のパスワードだと盗まれたらそのまま使われるからです。
ハッシュ値なら元のパスワードや同じハッシュ値になる文字列を探すのが困難になります。
困難さはアルゴリズムによって変わります。

同じ文字列をハッシュ化しても同じハッシュ化された文字列にはなりませんよね?

なります。

投稿2019/11/13 10:24

dameo

総合スコア943

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

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

Zuishin

2019/11/21 23:38

ハッシュ値から複合化できるように読めますが、できません。同じハッシュ値を生むキーを生成することならできることもあります。
dameo

2019/11/21 23:44

何を言いたいのかよく分かりませんが、「ハッシュ値なら元のパスワードや同じハッシュ値になる文字列を探すのが困難になります。困難さはアルゴリズムによって変わります。」で何か間違っているのでしょうか?
退会済みユーザー

退会済みユーザー

2019/11/21 23:51 編集

> 困難さはアルゴリズムによって変わります。 こっちも微妙な気がします。 解析作業=総当り/困難さ=時間 を指すのであればですが、その場合は、(総当たりの総数と)ストレッチングの回数が困難さを決定させる要素の殆どになるかと。
Zuishin

2019/11/21 23:47

ハッシュ値から元のパスワードを探すのは困難であって不可能ではないと書いているように読めますが、ハッシュは不可逆です。
Zuishin

2019/11/21 23:52 編集

簡単なハッシュ計算をしてみましょう。すべての自然数からハッシュ値 1 か 0 を作るハッシュアルゴリズムがあります。具体的には n % 2 です。ではハッシュ値 1 から元の自然数を求めることは可能でしょうか? このようなものを不可逆と言います。
dameo

2019/11/21 23:54

@te2jiさん まず前提にアルゴリズムがあると思います。その後ストレッチングについては、実装依存であり、ここでは説明を省略し、パスワードとだけ書いています。アルゴリズムの入力として何があるかは、アルゴリズム依存であり、パスワードをそのままパスワードとして使うか、或いはある種の変換をかけるかは実装により任意だからです。 @Zuishinさん 不可逆なのは、一意に戻れないだけで、天文学的時間をかけられるなら、パスワードや同じハッシュ値になる文字列を見つけられるでしょう。
Zuishin

2019/11/21 23:57

見つかったパスワードが正しいかどうかはどうやって確かめますか? 3 でも 5 でも 7 でも 9 でもハッシュ値は 1 になります。一つ一つに天文学的時間をかけてすべての自然数を精査することが仮にできたとしても、元の値が正しいかどうかを確かめる手段がないので復号は不可能です。
Zuishin

2019/11/22 00:00

> 元のパスワードや同じハッシュ値になる文字列を探すのが困難 同じハッシュ値になる文字列を探すのは困難です。 元のパスワードを探すのは不可能です。
dameo

2019/11/22 00:03

@Zuishinさん えーっと…それを一意に戻れない、と言ったのですが… どうやら話に齟齬があるようですね。 私が「復号できる」と言ったのは、 「例えばログインする際、暗号化であれば例えばBASE64などは一定の法則があって復号化が可能で、DBに入っている文字列を復号化し入力した値を照らし合わせるということが出来る」 という質問者の引用の条件を満たす場合の話です。ここでは質問者自身が復号化可能なことを前提条件にアルゴリズムを選択しています。
Zuishin

2019/11/22 00:04

初めに書いたように、元のパスワードを探すことが可能であるように読め、読者に混乱を招いています。
dameo

2019/11/22 00:06

いやそうは思いませんが…
Zuishin

2019/11/22 00:07

> 元のパスワードや同じハッシュ値になる文字列を探すのが困難 「や」の意味はご存じですか?
Zuishin

2019/11/22 00:08

並列に並べられています。
Zuishin

2019/11/22 00:08

> 出来るといえば出来ますが、復号はしないのです。 これも BASE64 の話には読めません。 復号しないのは BASE64 ではなくハッシュです。
Zuishin

2019/11/22 00:12

> 出来るといえば出来ますが、復号はしないのです。 > 同じようにハッシュ値を計算してそれが一致することを確認するだけです。 この二行から、省略された主語が BASE64 と読むのは困難です。
dameo

2019/11/22 00:14

前にも思いましたが、失礼を承知でいうと、ちょっとおかしいですよ。 落ち着いてください。リソースの無駄になるので私からの返事はここまでで…
Zuishin

2019/11/22 00:18

まあここまででしょうね。私ならまともな回答に編集しなおしますが。
退会済みユーザー

退会済みユーザー

2019/11/22 02:09

解析作業=総当り/困難さ=時間 の前提であれば、ハッシュ文字列の解析の困難さは「アルゴリズム」ではなく「実装」によって左右されるって指摘なんですけど理解していますか? 暗号学的に安全なアルゴリズムさえ選択していれば、解析にかかる想定時間は、文字列の組み合わせ総数とストレッチング回数の影響がほとんどです。
dameo

2019/11/22 02:32

> 暗号学的に安全なアルゴリズムさえ選択していれば、解析にかかる想定時間は、文字列の組み合わせ総数とストレッチング回数の影響がほとんどです。 私が言っているのは、アルゴリズムの入力を「パスワード」という単語で略記しているということです。 そして、te2jiさんがおっしゃっているのは、アルゴリズムの入力には、ストレッチングしたものが使用できます、ということです。そこに齟齬がある間は話が成立しません。 ハッシュ値はあくまでも入力に対して計算されたハッシュ値です。ストレッチングはやりたければいくらでも出来ますし、任意で実装依存です。例えばアルゴリズムを複数個逐次的に適用したっていいわけです。でもそれを今の概念理解のための議論の中に入れる必要はありません。
退会済みユーザー

退会済みユーザー

2019/11/22 02:37

> 困難さはアルゴリズムによって変わります。 これ、何を指しています?
dameo

2019/11/22 02:40

文脈から「元のパスワードや同じハッシュ値になる文字列を探す」ことの困難さですよね…
退会済みユーザー

退会済みユーザー

2019/11/22 02:42

困難さとは?
dameo

2019/11/22 02:47

そんな汎用な日本語を説明する必要があるとは思いません。 時間ないんですけど…
退会済みユーザー

退会済みユーザー

2019/11/22 02:51

理解を諦めたようなので低評価しておきますが、色々間違ってますよ。
dameo

2019/11/22 03:04

評価はご自由に。ただ自分の誤解を人のせいにしてはいけませんよ。 話の齟齬をきちんと説明しますね。正確ではないですが、大雑把にこういうことです。 アルゴリズムをf 入力をi ハッシュをhとすると h=f(i) となります。hからiを求める逆関数gが定義できたとして i=g(h) です。iは複数解があるので不可逆で、gの計算にかかる時間はfに依存します。 一般的なストレッチングはソルトを使って行うので、 ストレッチングするアルゴリズムをs ソルトをaとし、パスワードをpとします。すると h=f(s(p,a)) となるってことです。私は、fの入力s(p,a)をパスワードと略記していると言っているだけです。 理由はfとsは任意で無関係であり、概念的にはそれぞれ別個に考えればいいからです。 逆関数の実行時間=解析の難易度もそれぞれ考える必要があります。 理解できなければ諦めてください。話は終わりです。
退会済みユーザー

退会済みユーザー

2019/11/22 03:16

> gの計算にかかる時間はfに依存します。 これが間違っています。 だから実装に依存するって言っているのに。。。
dameo

2019/11/22 03:28

諦めてくださいと言ってるんですが…勘弁してください… sにも逆関数があり、そこにかかる時間があるだけです… gで求めているのはs(p,a)であり、pではありません
退会済みユーザー

退会済みユーザー

2019/11/22 03:35

回答が正しく整理されることが理想なのですが、無理っぽいですね。
dameo

2019/11/22 03:47

あなたが一体何を誤解していて、何を不満に思ってるのか見当が付きませんね。 「gの計算にかかる時間はfに依存」せず、実装に依存してるのですか??? 一体何の実装に依存してるのでしょう?
退会済みユーザー

退会済みユーザー

2019/11/22 03:54

有名どこではレインボーテーブルがそうでしょ。f 以外に依存する。
dameo

2019/11/22 03:57

それfに思いっきり依存してますよね… md5でもsha256でも同じテーブルだという主張になりますよ
退会済みユーザー

退会済みユーザー

2019/11/22 04:01 編集

依存しないですよ。事前に計算していて、時間的には還元関数に依存します。
退会済みユーザー

退会済みユーザー

2019/11/22 04:01

だから「困難って?」て聞いてるのに^^;
dameo

2019/11/22 04:02

ん?テーブルありきのアルゴリズムで計算時間だけならそうなりますね でも、それは辞書攻撃だと普通にそうなりますし、辞書になければ終わりで、gとは別
退会済みユーザー

退会済みユーザー

2019/11/22 04:06

> ん?テーブルありきのアルゴリズムで計算時間だけならそうなりますね だから「困難って?」て聞いてるのに^^; dameo さんのコメントだと g がレインボテーブル攻撃と重なるんですよ。 だから間違ってるって言ってるんだし。
退会済みユーザー

退会済みユーザー

2019/11/22 04:09 編集

で、g を(現実的に)レインボー攻撃等の総当り以外の解析手法から「別にするための方法」がサルトとストレッチングの実装です。
Zuishin

2019/11/22 04:13

関数と逆関数の困難さが常に比例するというのは明らかに間違っています。 簡単な例で言えば、因数分解の困難さは因数の乗算の困難さに比例しません。
dameo

2019/11/22 04:13

辞書攻撃を回避するために乱数生成のソルトを保存するのは知ってるし、ちゃんとs(p,a)で書きましたよ。 辞書攻撃が有効なのはi=pのときが顕著で、ストレッチしたとしてもsとaが知られていない前提のときです。
dameo

2019/11/22 04:14

@Zuishinさん 関数と逆関数の困難さが常に比例するなんて言ってませんよ
Zuishin

2019/11/22 04:20

> gの計算にかかる時間はfに依存します。 比例ではなく依存でしたね。しかし f と g は全く別のアルゴリズムが考えられるので、別個に考えるべきものだと思います。f の逆関数は様々なアルゴリズムが考えられるので、依存するとは言いにくいです。
退会済みユーザー

退会済みユーザー

2019/11/22 04:25 編集

> 辞書攻撃を回避するために乱数生成のソルトを保存するのは知ってるし そんな事は指摘してないんですけどねぇ。。。 (辞書攻撃に対応するのはどちらかというとストレッチングです) 指摘しているのは、実装によっては g を使用した処理はごく短時間で済む可能性があるってことです。 多分レインボー攻撃もよく理解できていないのでは? ちなみに一般的なストレッチングで解析作業が 2^10 から 2^11 倍程度の時間がかかるようになることは理解されてます? もともと指摘しているのは、 解析作業=総当り/困難さ=時間 である時の指摘なので随分ずれてきてしまっていますが指摘ポイントが多すぎて発散してしまいますね。。。
dameo

2019/11/22 04:31

@Zuishinさん 特定の条件で求められるのはどのアルゴリズムでも同じですよ。 ここでは一般解の話だけでいいはずです。 @te2ji gの一般解の話と、特定条件の話を勝手に混ぜないでください。 どのアルゴリズムでも、先の話の h=f(s(p,a)) で、f,s,aがわかっていれば、pによる辞書攻撃は可能です。 ストレッチングで云々という話は、辞書攻撃をする場合でも、単にfだけ分かっているケースでは、sの逆関数分だけ時間がかかると言っているだけの話です。
Zuishin

2019/11/22 04:33

一般解の話です。逆関数の困難さは逆関数のみに依存し、関数には依存しません。
Zuishin

2019/11/22 04:34

別の表現をするなら、関数の困難さは逆関数に依存しません。
dameo

2019/11/22 04:45

@Zuishin 一般解では逆関数が元の関数に依存せずに決まるケースなんて思いつかないんですが…
Zuishin

2019/11/22 04:47

困難さの話ですよね?
Zuishin

2019/11/22 04:49

乗算の逆関数は除算ですが、除算のアルゴリズムは複数あります。 依存というのはどういう意味ですか?
退会済みユーザー

退会済みユーザー

2019/11/22 04:50

h=f(s(p,a)) は h=s(f(p,a)) のはずですが、誤記ですか? 多分、全体的に上の式で理解しているように見えるので、根本が間違っている気がします。 > gの一般解の話と、特定条件の話を勝手に混ぜないでください。 先にも記述しましたが「dameo さんのコメントだと g がレインボテーブル攻撃と重なるんですよ。 」 特定条件を排除するために必要なのがサルトとストレッチングの実装と言っています。
dameo

2019/11/22 05:11

@Zuishinさん 一般解で逆関数を決めずに実装だけする方法があるということですか? それは多分総当りしか出来ないと思うので、現実的には無限時間必要で一般解とはなりえません @te2jiさん ストレッチングってsにも当てはまると思ってました。違ってましたね。すみません。きちんと書くなら h=fn(...f2(f1(s(p,a)))...) みたいな感じで、f1~fnみたいな部分がストレッチングです。ここではストレッチングは概念から外して、 f(i)=fn(...f2(f1(i))...) のようにアルゴリズムの特殊な形と考えてください。sは便宜上以降ではソルト関数と呼んでおきます。 すると h=f(s(p,a)) でいいはずです。 > 先にも記述しましたが「dameo さんのコメントだと g がレインボテーブル攻撃と重なるんですよ。 」 gは一般解なので、特定条件だけの解で同一視はできません。 ソルトの話はiの中に入っているので、大丈夫です。
Zuishin

2019/11/22 05:13

逆関数が関数に依存するというのはどういう意味かと聞いています。
Zuishin

2019/11/22 05:15

ハッシュには微分方程式を使わなければならないという前提で書いていますか?
dameo

2019/11/22 05:16 編集

@Zuishinさん AがBに依存してると言ったら、AがBに無関係に決まらないってことではないですか? 日本語的に…
Zuishin

2019/11/22 05:18

そんな日本語は知りませんね。ブラジル方面で使われている言葉ですか? A が B に依存していると言ったら、ふつうは A が B の状態によって変化するという意味です。
Zuishin

2019/11/22 05:19

そのような一般的な定義ではなく、この文脈ではどういう意味でつかわれているのかを聞いています。
Zuishin

2019/11/22 05:20

この文脈というのは次の文の文脈です。 > gの計算にかかる時間はfに依存します。
dameo

2019/11/22 05:25

@Zuishinさん 普通の日本語だし、文脈的にもさっきの説明のとおりですけど...落ち着いてください
Zuishin

2019/11/22 05:26

では落ち着いて答えてください。 次の文はどういう意味ですか? > gの計算にかかる時間はfに依存します。
dameo

2019/11/22 05:33

@Zuishinさん 「AがBに依存してると言ったら、AがBに無関係に決まらないってこと」なので、 「gの計算にかかる時間はfに依存します。」ってことは 「gの計算にかかる時間がfに無関係に決まらないってこと」なのではないですか? ほんとに大丈夫ですか?
Zuishin

2019/11/22 05:35 編集

落ち着いて聞かれたことに答えてください。
dameo

2019/11/22 05:40

@Zuishinさん あなたのコメントのすぐ上にありますけど...
Zuishin

2019/11/22 05:42 編集

言い忘れていました。日本語で答えてください。
Zuishin

2019/11/22 05:44

例えば f が除算だとします。そして g が乗算だとします。 f のアルゴリズムによって g の計算時間が変わるというのは私にとって信じがたいことです。
dameo

2019/11/22 05:54

@Zuishinさん あなたが勝手に日本語じゃないと言い張っても、日本語であることには変わりませんし、普通に使います。 fのアルゴリズムがCRCでも、sha512でも、gの計算時間が一律同じにはならないってことですよ。当たり前ですよね。 te2jiさんが言ってたのは、(簡略化しますが)予め計算された辞書があれば、辞書にある範囲(特定条件)ならfのアルゴリズムがなんであれ、gの計算時間が一律になるって話です。
Zuishin

2019/11/22 05:55

g の計算時間は g のアルゴリズムに依存します。
Zuishin

2019/11/22 06:03 編集

f が CRC であろうが sha512 であろうが何であろうが g がテーブルから引いて総当たりするというアルゴリズムならかかるのは同じ時間です。
Zuishin

2019/11/22 05:57

それともハッシュ関数の逆関数というのはそのアルゴリズムの逆に計算するという意味なのですか? そんなことができますか?
Zuishin

2019/11/22 06:00

もしそれができると信じているなら、不可逆について一度調べてみてください。
dameo

2019/11/22 06:04

@Zuishinさん 書いた通り h=f(i) i=g(h) を満たす、関数です。fとgはプログラミング言語の関数と思ってくれればいいです。 もちろんfは1:1の写像でない場合もあるので、gの解が複数あるものもあります。 そういう説明をここまでしてきているんですけどね…
Zuishin

2019/11/22 06:07

その話をしています。落ち着いてまず不可逆とは何か調べてきてください。
dameo

2019/11/22 06:10

不要です。。。
Zuishin

2019/11/22 06:16

g のアルゴリズムが、各ハッシュとそれを生成するキーのテーブルからキーを得るものであった場合、g の計算時間は f に依存しません。
dameo

2019/11/22 06:21

当たり前ですが、それは一般解にはなりえません。 一般には全iに対するデータを用意できないからです。
Zuishin

2019/11/22 06:23

これは一例にすぎません。
Zuishin

2019/11/22 06:25 編集

(この発言は失礼と受け取れるので撤回し編集します)
Zuishin

2019/11/22 06:30

一例というのはつまり、あなたの理論の反証、反例ということです。反例はわかりますか?
dameo

2019/11/22 06:36

だから一般解にならないって言ってるでしょ... 一例とかすでに否定されてるんですよ 人の話聞きましょうよ 会話が成立しない
Zuishin

2019/11/22 06:37

あなたの理論の基礎が反例によって崩壊したのがわかってないから話にならないんじゃないですかね。 シャワーでも浴びてホットミルクでも飲んできてください。
maisumakun

2019/11/22 06:41

> 出来るといえば出来ますが、復号はしないのです。 同じようにハッシュ値を計算してそれが一致することを確認するだけです。 Base64の復元はできますが、ハッシュ化した元データは衝突するので復元は原理的に不可能です。両者は本質的に異なります。
退会済みユーザー

退会済みユーザー

2019/11/22 06:46

> sは便宜上以降ではソルト関数と呼んでおきます。 > すると h=f(s(p,a)) でいいはずです。 なんか定義変えたり無茶苦茶じゃないですか^^; 会話の途中で定義変えられると会話が成立しないので、こちらの言いたかったことを記述しておきます。 ・ハッシュ値から元のパスワードを探す場合、一定の条件を満たさない限り、レインボーテーブルを使用した攻撃や同一パスワードが同じハッシュとなってしまう統計学的な解析が有効になり、解析の困難さ(解析にかかる時間)はハッシュアルゴリズムに依存しなくなります。 ・一般的には上記のような解析を回避するために、実装で工夫します。 ・一定条件を回避するための一般的な手法は、サルトの追加/ストレッチングの実施です。 ・ストレッチングを実施するならハッシュアルゴリズムによるハッシュ作成時間は、解析の困難さ(解析にかかる時間)に余り影響を与えるものではないです。 以下、影響を与えない理由 一般的にパスワード照合にかけられる時間は無制限ではないので、ある一定水準となるようにストレッチング回数は調整することになります。 例えば、パスワード照合にかけられる時間が要件として 50 ms だったとして、低スペックのサーバではストレッチング回数少なくし、高スペックのサーバでは増やし 50 ms を目指します。 また、使用するハッシュアルゴリズムがサーバリソースをそれほど消費しない場合はストレッチング回数を増やし、リソースを消費する場合はストレッチング回数を減らし、50 ms を目指します。 つまり、一定時間を目指すためストレッチング回数を調整するので、ハッシュアルゴリズムが何でもあまり関係ありません。 サービス提供サーバでストレッチングも含めた時間と比例しただけの時間がかかります。 *実際には解析用のサーバとサービス提供用のサーバの得手不得手によりハッシュアルゴリズムの関係性はゼロではないですけど。 上記の為、解析作業=総当り / 困難さ=時間とすると、実装(サルトとストレッチング)を無視した議論に意味は無く、実装した場合の議論ではハッシュ文字列の解析の困難さは「アルゴリズム」ではなく「実装」によって左右されるって指摘でした。
dameo

2019/11/22 07:05

>Zuishinさん 単純な辞書攻撃は、何をしようと可能です。 ブラウザでログイン画面に入力すればいいわけですから。 通常こういう攻撃は認証失敗時にウェイトを入れたり、単位時間辺りの認証回数を制限したりすることで緩和しますが、概念上扱う問題ではなく、運用上必要になる話なのですよ。 パスワードにソルトを入れたり、アルゴリズムそのものを組み合わせたりするのも、同じ理屈です。 @maisumakunさん だから、「元のパスワードや同じハッシュ値になる文字列」は複数解存在すると言っていますよ。 そして解読する人にとっては、どれか1つ求められればいいのです。 @te2jiさん 定義を変えたと言っても、大筋は変わってないですよ。少なくとも会話に影響はなさそうです。 一度書きましたが、レインボーテーブルは一般解ではなく辞書攻撃のようなものです。 これは理論上どうこうするものではなく、運用で実装回避する類の話です。 gは一般解を求める話と混同しないでください。 もしその話を認めてしまうと、fはSHA512とかでなくCRCでもいいってことになってしまいます。 話が一向に噛み合わないですね。
Zuishin

2019/11/22 07:11 編集

話が噛み合わないので、回答を普通の日本人に通じるよう編集し直して頂けばいいのではないかと思います。
退会済みユーザー

退会済みユーザー

2019/11/22 07:11

そりゃ g が一般的に存在するって人とは会話合わないですよ^^; g が一般的に存在しないから総当りなんて手段で解析するんで。
maisumakun

2019/11/22 07:21 編集

> そして解読する人にとっては、どれか1つ求められればいいのです。 ログイン認証にはそれでは役立たないです(「どれか1つ」として別なパスワードが得られてしまったら、正しいパスワードでも認証に失敗します)。元のパスワードをハッシュ化する「しか手段がない」です。
dameo

2019/11/22 07:20

@Zuishinさん すみませんが、会話成立してないんで以降は無視しますね @te2jiさん fによらずgが必ず数学関数的に存在するとは言っていませんよ。 ある程度以上の複雑なfは多少の枝刈りが出来るだけで総当りに近い解析になると思います。 ただ、それは解析難易度/計算時間という意味で、fの評価に繋がります。 全部一緒じゃありません。
dameo

2019/11/22 07:22

@maisumakunさん 同じハッシュ値になる文字列でも認証されてしまうと思いますよ
Zuishin

2019/11/22 07:23

反論できないと煽るか無視なんですね。
maisumakun

2019/11/22 07:25

> 同じハッシュ値になる文字列でも認証されてしまうと思いますよ されない場合があります。 1. ユーザーの登録したパスワード「ABCDEFGHIJ」→ハッシュ値「xxxxx」を保存 2. ユーザーがログインしようとして、正しくパスワードを入力 3. ハッシュ値からパスワードを復元すると、衝突していた「123456」が得られてしまった 4. 照合結果は不一致 ということで、「ハッシュ値を戻す」方法でユーザー認証を行うのは不適当です。
退会済みユーザー

退会済みユーザー

2019/11/22 07:32

特定条件下で存在しうる g としてレインボーテーブルによる攻撃をあげました。 それに対して > gの一般解の話と、特定条件の話を勝手に混ぜないでください。 とあります。 特殊条件でない g が存在する状況ってなんですか?具体的に示してください。
dameo

2019/11/22 07:33

@maisumakunさん 私が言っているのは、 1. ユーザーの登録したパスワード「ABCDEFGHIJ」→ハッシュ値「xxxxx」をDBに保存 2. 悪い人がユーザー名とハッシュ値のペアをDBから盗む 3. 悪い人がハッシュ値からパスワードを解析/復元したら「123456」が出てきた 4. 悪い人が盗んだユーザー名とパスワード「123456」を使ってログイン →成功すると思う(saltとかない場合) ってことです。
dameo

2019/11/22 07:35

@te2ji 無限に長いパスワードを設定できる状況と言えばいいのでしょうかね。 概念的な話なので。
maisumakun

2019/11/22 07:38 編集

> 私が言っているのは、(中略)ってことです。 そこに言及したつもりはありません。もとの回答の「出来るといえば出来る」というのは、「ログイン認証」という場面では不適当、という話です。
退会済みユーザー

退会済みユーザー

2019/11/22 07:39

無限に長いパスワードを設定できる状況だと g が存在すると言ってるのですか? ちょっと理解できませんが。。。
dameo

2019/11/22 07:44

@maisumakun もとの回答で引用しているのは写像1:1の復号可能なアルゴリズムであるBASE64についてですよ。 なので出来ると言っているのは復号可能なアルゴリズムを想定しています。 以下の続く文ではハッシュ値という言葉を使い、そうでないアルゴリズムも含めています。 @te2ji 辞書を使わずに、(ある程度以上複雑なfだと)ほぼ総当りをやるってだけですよ...
maisumakun

2019/11/22 07:46

> なので出来ると言っているのは復号可能なアルゴリズムを想定しています。 以下の続く文ではハッシュ値という言葉を使い、そうでないアルゴリズムも含めています。 その2つを「同じように」でつないでしまうのが理解できません。
dameo

2019/11/22 07:52

@maisumakunさん 確かに文意としては、「同じように」の前に「非可逆/復号不可能なアルゴリズムと」を付けた方が分かりやすいかもですね。読み取れると思いましたが…
退会済みユーザー

退会済みユーザー

2019/11/22 07:52

> 辞書を使わずに、(ある程度以上複雑なfだと)ほぼ総当りをやるってだけですよ... 上記、全く今までの g の意味と異なり意味がわからないです。 仮にそれを g の存在というのであれば、g が存在しない状況って無いと思いますが。。。 > fによらずgが必ず数学関数的に存在するとは言っていませんよ。 意味がわからん。
dameo

2019/11/22 07:59

@te2jiさん だから始めに「hからiを求める逆関数gが定義できたとして」という仮定を入れており、実質プログラミングで逐次的に求めることも想定しています。数学的というのは、方程式のように解けるかどうかを指しているだけですよ。
退会済みユーザー

退会済みユーザー

2019/11/22 08:09

g を > 辞書を使わずに、(ある程度以上複雑なfだと)ほぼ総当りをやるってだけですよ... とすると、 > 「hからiを求める逆関数gが定義できたとして」 に対して、また定義がずれてくるのですけれど。。。 逆関数って何なんでしょうか?
退会済みユーザー

退会済みユーザー

2019/11/22 08:16 編集

なんか会話の矛盾を指摘していくだけで生産性無いので、再度指摘だけしておきますね。 > 困難さはアルゴリズムによって変わります。 解析の困難さは実装で変わります。 サルトとストレッチングを使用してください。
Zuishin

2019/11/22 08:19

100 個目のコメントをお知らせします。
Zuishin

2019/11/22 08:22

続きまして、もう本人も自分で何言ってるかわかってないんじゃないか説を提唱します。
dameo

2019/11/22 08:36

@te2ji h=g(i) を満たす関数ですよ… 解析の困難さはアルゴリズムによって変わりますって。 fが入力の先頭からハッシュの長さ分切り取って、ハッシュと言い張るアルゴリズムだった場合と、 fがsha512とかだった場合の解析の困難さが同じですか? 違うのですよ。 パスワードにソルトやペッパーを使って味付けしたものを入力にするのは運用上必要な措置です。 しかし、概念の理解に必ずしも必要な話ではありません。
dameo

2019/11/22 08:39

ただし、ハッシュと一緒にソルトを持ち出され、ハッシュの算出ロジックを解析されたなら、同様なリスクがあります。ソルトの場所や使い方はそれなりの工夫をした方がいいかもです。
退会済みユーザー

退会済みユーザー

2019/11/22 08:51

おー!理解できたw 暗号学的ハッシュ関数以外のハッシュ関数の使用を含めた回答だったのか! 話が噛み合わんわけだわ。 そもそものハッシュ関数の定義がずれてたのね。 途中で暗号学的に安全なハッシュに関しての会話だってこちらが言及してるんだからそこで言ってくれればいいのに。
退会済みユーザー

退会済みユーザー

2019/11/22 08:55

暗号学的に安全なハッシュ関数っておかしいな^^; 乱数とごっちゃになってる。暗号学的ハッシュ関数が正しいですね。
dameo

2019/11/22 09:10

@te2jiさん 質問者さんの意向にそって回答したらそうなっただけですよ BASE64のハッシュ?なんて考えたくもありません笑
guest

0

参考情報

  • パスワードハッシュ化で用いるソルト(Salt)とペッパー(Pepper)/シークレットソルト(Secret Salt)の役割と効果

https://qiita.com/shioshiota/items/d439e63c4ee651d956ab

...
Saltの役割は下記の二種類です。
同じパスワードでも算出されるハッシュ値が異なるようにすること
一方向関数への入力文字列を長くすること
...

  • deviseで使用しているbcryptによるencrypted_passwordの挙動

https://qiita.com/kenjiszk/items/d38e398bc120cf4bbd1c

...
ログイン時にデータベースに保存されているencrypted_passwordと、ユーザーが入力して来た平文のパスワードの比較をする為に以下のメソッドが定義されている
...

投稿2019/11/15 23:18

katoy

総合スコア22324

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

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

0

どのような文字列も同じ文字列をハッシュ化すれば常に同じになります。
対して同じ文字列を暗号化したらその都度変わってしまいます。

ちなみに暗号化がその都度変わる実験はこちらを参考にしてください。

投稿2019/11/13 09:43

編集2019/11/13 11:19
kyoya0819

総合スコア10429

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

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

kyoya0819

2019/11/13 09:45

ただ、セキュリティの観点からはソルトすることが必須でありそうなるとまた話は別になっていきます。
退会済みユーザー

退会済みユーザー

2019/11/13 10:47

「一様性」って言葉が聞き慣れなかったので微妙な指摘になりますが、一段目と三段目が間違っているかと。 文字列のハッシュ値を取った場合、同じ文字列では必ず同じハッシュ値になりますが、同じハッシュ値であるものの元が同じ文字列である保証はありません。 暗号化の場合は、可逆でなければならないので、必ず1対1対応となります。
kyoya0819

2019/11/13 10:58

独自の言葉を使ってしまったようですみません。 この場合の一様性は特定の文字列のハッシュ化・暗号化後の文字列が常に同じになるかどうかと言うことです。
dameo

2019/11/13 14:23 編集

実験のコードを見ましたが、少し補足しますね。 暗号化されたデータは毎回違いますが、初期化ベクタが毎回違います。 復号時にこれは合わせないといけないわけで、同じ文字列を同じ鍵と同じ初期化ベクタで暗号化した場合は、毎回同じ暗号データになります。 鍵と初期化ベクタを合わせることで、復号出来るということです。
退会済みユーザー

退会済みユーザー

2019/11/13 15:17 編集

IV は誤解を恐れずに言えば、salt のポジションですね。
dameo

2019/11/13 15:05

そうだと思ったんですけど、よく見たらphpの当該関数にはそのような指定がなかったので、全部渡すものなのかなぁ…鍵交換の他に大変だなぁと思いつつ、そう書くのは止めました。実際のTLSでどう実装されてるのかは素人なので知りません。詳しい人が見ててくれたらいいんですけども…
退会済みユーザー

退会済みユーザー

2019/11/13 15:17 編集

AES-256-CBC を使用する以上は、IV の変更まで含めて暗号化だ!ってのが asuchi0819 さんの主張だと思います。 https://teratail.com/questions/65106 こちらの ikedas さんの回答がわかりやすいです。
dameo

2019/11/13 15:22

初期化ベクタが毎回違う前提とは、関係ない話ですね。お話が発散しそうなので、やめときます。
kyoya0819

2019/11/13 23:19

> AES-256-CBC を使用する以上は、IV の変更まで含めて暗号化だ!ってのが > asuchi0819 さんの主張だと思います。 そうですね、個人的には。
dameo

2019/11/14 00:16

う~ん、散らかりそうですが、私が言ってたことを説明しておきますね。 例えば、パスワード付きのZIPファイル。これをメールで送付とかは大きな会社の人でも平気でやります。かけないよりマシという程度の話ですが、ご存知のとおりこれも共有鍵方式の暗号化であり、 パスワードしかない以上、IVも固定です。ソルトがあったとして固定ですよね。だから総当りや辞書攻撃にとても弱いです。 でも仕方ないですよね。復号化の際にパスワード以外のデータを使用出来ないのだから。だからと言ってこれも立派な暗号化です。 暗号化の場合、主に利用されるシーンは暗号化通信だと思います。 この場合は、公開鍵暗号による安全な鍵交換が可能なので、実際のデータ部分は共有鍵方式で暗号化されます。この暗号化を行う際に、固定の初期化ベクタを使用すると、クッキーを起点に解析するなどの攻撃が可能なので、初期化ベクタを通信ごとに変えるなどの対策が必要ということになります。 ただ、共有鍵方式の復号化に直接必要なデータは共有鍵方式で通信する前に、分かっていないといけないので、鍵交換と同じタイミングで同じように共有できないといけないのです。この仕組みが素人なので分からないと言っていました。もしこのとき種っぽいものを使って初期化ベクタを生成するのであれば、ソルトと言ってもいいのかなぁと思ったのですが、初期化ベクタそのものを渡すのであればソルトというと語弊があると思った、というだけのことです。
kyoya0819

2019/11/14 00:18

dameoさんがおっしゃる「ソルト」がわたしの最初のコメントだとしたらすみません。最初のソルトは「ハッシュ化」に対する「ソルト」になります。
dameo

2019/11/14 00:23

違いが分かりません。。。とりあえず説明しておこうと思っただけなので、すみません。
kyoya0819

2019/11/14 00:25

そもそも「ソルト」の定義が 暗号理論におけるソルトとは、パスワードやパスフレーズなどのデータをハッシュ化する際に、一方向性関数の入力に加えるランダムなデータのことである。 (Wikipedia) なので語弊があるといけないと思いコメントしました。
dameo

2019/11/14 00:34

まあその定義では違うんですよね。 一般的ではないかもしれませんが、seedでもsaltでもあまり区別していませんでした。
macof

2019/11/14 00:52 編集

dameo さん 細かいことを言うようで申し訳ありませんが、 Zipを同じキーで暗号化しても同じ結果にはなりませんよ。 そのためのIVというか、CBCですので。 同じキーおよびソースで同じ結果になって良いのであれば、そもそもCBCではなくECBを使えば良いということになります。 追記 ECBだと途中のブロックの置換等への耐性も下がるなどの問題もありますので単純にECBで良いというのは言い過ぎでした。 申し訳ありません。
dameo

2019/11/14 00:53

なんと!IVはファイルの中に入ってるってことです? まあでもファイルに入ってたら同じことでは…
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問