ハッシュ関数について質問です

このQ&Aのポイント
  • パスワードとSALTを一緒にしてハッシュ関数を通してハッシュ値を取得する方法について質問です。
  • あるハッシュ関数を使用すると複数のハッシュ値が生成されますが、その全てが特定のパスワードから生成されたものですか?
  • 別のタイプのハッシュ関数について質問です。その仕組みや存在について教えてください。
回答を見る
  • ベストアンサー

ハッシュ関数について質問です。

プログラミング・数学? 初心者です。 IDやパスワード管理によく出てくる一次方向(ハッシュ)関数ですが、 よくパスワードとSALTを一緒にしてハッシュ関数を通してハッシュ値を取得しますよね。 そしてその結果(データベースなどに記録済み)とログイン時に入力した値とを照らし合わせるわけですが、 昔まだ若いころ、これとは別のタイプのハッシュ関数を使用したことがあります。 それはある(パスワードなどの)値をハッシュ関数で処理すると「いろんなハッシュ値」が生成され、 そのハッシュ値から当然パスワードは予測できないのですが、 しかしその複数のハッシュ値は全て、そのパスワードから生成されたハッシュ値だということは分かる、という関数を使用したことがあります。 その時はperlのcpanモジュール(名前を覚えていません。すいません。)を使ったのですが、この別のタイプのハッシュ関数はどういう仕組みで作られているのでしょうか? SALTが複数あり、そのそれぞれについて照合している?だけでしょうか? それとも私が無知で、そんな関数がそもそも存在するだけでしょうか? わかりません。教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

crypt関数のようにパスワードの生成を目的とした関数でダイジェスト (質問者が言うところのハッシュ値) を作る場合、普通ダイジェストにはSALTの値が含まれています。 例えば、Perl標準のcrypt関数は、SALTとしてダイジェストを渡すとそこからSALTを自動的に取り出して、与えられたパスワードと本のダイジェスト生成時に使ったSALTを使ったダイジェストを計算します。 http://perldoc.perl.org/functions/crypt.html よって、Perlのcrypt関数を使ったパスワードの検証は次のようにすると上記マニュアルでも説明されています。 | crypt($plain, $digest) eq $digest 質問者が言うところのCPANのモジュールはこれをラップしたようなモジュールだと予想します。 つまり、ハッシュ値を計算する関数を呼ぶと乱数などから自動的にSALTを作成し、ハッシュ値を返す。正しいパスワードか検証する関数は、ダイジェストと一緒に渡すと勝手にSALTを取り出して計算して一致、不一致を教えてくれるという動きをするのでしょう。 実際にコードで書くとこんな感じでしょうか。 (SALTが短く選び方も雑ですが、分かりやすさを重視してそこら辺は手抜きしてます) sub my_crypt { my ($password) = @_; my @salt_candidate_chars = ('a' .. 'z', 'A' .. 'Z', '0' .. '9'); my $salt = $salt_candidate_chars[int(rand($#salt_candidate_chars + 1))]. $salt_candidate_chars[int(rand($#salt_candidate_chars + 1))]; return crypt($password, $salt); } sub my_verify { my ($password, $digest) = @_; return crypt($password, $digest) eq $digest; } my $d = &my_crypt("password"); print "digest: $d\n"; print "wrong:" . &my_verify("wrong", $d) . "\n"; print "correct:" . &my_verify("password", $d) . "\n"; > その時はperlのcpanモジュール(名前を覚えていません。すいません。)を使ったのですが、この別のタイプのハッシュ関数はどういう仕組みで作られているのでしょうか? ランダムにSALTを生成する上記のような仕組みだと思います。 > SALTが複数あり、そのそれぞれについて照合している?だけでしょうか? SALTが複数あるというより、上記のようにランダムに作っていると予想します。 そして、SALTがハッシュ値 (というか、ダイジェスト) と一緒に出力されていると思います。 当然、検証の時はダイジェストも渡しますよね?

okwave67232
質問者

お礼

回答ありがとうございます。昔の事なので、今となっては曖昧な記憶しかありませんが、たぶんhanabutakoさんの言うとおりだと思います。ありがとうございます。

その他の回答 (1)

  • hateri
  • ベストアンサー率46% (7/15)
回答No.1

crypt関数のことだと思うので、詳しいことは参照URLの閲覧をお願いします。 ランダムに生成されたsaltキーに関しては、生成されたハッシュ文字列に含まれるので、 1.保存されているハッシュ文字列からsaltキーを抜き出す。 ↓ 2.入力されたパスワードとsaltキーを使って暗号化 ↓ 3.暗号化したものと保存されているハッシュ文字列が合っているかを検証 ↓ 4.認証 という手順です。 ちなみになぜsaltを使うのかというと、同じパスワードを設定していたとして一つがバレても、saltキーが違うおかげで生成されたハッシュ文字列が違うので、同じパスワードと気づかれないようにするのが大きな目的です。(他にもありますが。)

参考URL:
http://www.sea-bird.org/doc/Solaris8/Perl_5.html
okwave67232
質問者

お礼

回答ありがとうございます。勉強になりました。

関連するQ&A

  • DB内にMD5でハッシュ化されたパスワードとの照合

    MySQLのDBにMD5でハッシュ化されたパスワードが格納されているのですが、これをPerlのスクリプトで照合したいと思っています。 具体的には、DBに格納されているパスワードを用いて、Perlで作成された会員専用ページなどにログインをするといった感じです。 DBIを用いてDBからの情報を取得することはできたのですが、Perl側での対処がわかりません。 Perl側で入力されたパスワードをハッシュ化して、双方を照合するなどの情報を見たのですが、いまいち解らず認証することができませんでした。 以下にパスワードに関する部分のソースを記載させていただきます。 srand(); @salt = ( "A".."Z", "a".."z", "0".."9", ".", "/" ); $salt = '$1$' . join('', map($salt[int(rand(64))], 1..8)) . '$'; $pass = crypt($in{'pass'}, $salt); crypt($in{'pass'},$ary) eq "$ary") ※$aryはDB内に格納されているパスワードです Perlに関して殆ど解っていないもので、とんちんかんな記述かもしれませんが、ご教授いただけますと幸いです。 宜しくお願いいたします。

  • perlのハッシュについて

    perlのハッシュでキーから値を得ることは出来ますが、その逆に値からキーを得るような関数ってありますか?探してもみつかりませんでした。識者の方々教えてください。

    • ベストアンサー
    • Perl
  • 暗号学的ハッシュ関数でbit長が適切って作れますか

    SHA256が(224かもですが)最小bit長で、 入力に1bitでも、また2bit以上入力値全体まで、異なれば、 出力のうちほぼ半数のbitが反転する、かつその 反転するbit位置は複数の入力値に対して法則性はなく、 ほぼランダムである。 という暗号学的ハッシュ関数であるのは、正しいですか? また、データの暗号化に使われるパスワードは4096bitを推奨との 事ですが、 SHA4096などその時に合った暗号学的ハッシュ関数を 作るのは難しいのですか? 素人考えでは、今256bitで衝突が見つかってないなら 4096bitならbit長大きいのだから作れそうな気もしますが やはりそういう問題ではないのでしょうか? もし作れるとしたら、データの暗号化に使うパスワードを SHAなんとか・・・の出力そのまま使っては、危険でしょうか? というかデータに限らず認証のパスワードでも SHAなんとかの出力そのままを使うのは何かまずいのでしょうか? もしできたらパスワードを覚えなくてよいのでいいかと思ったのですが。 パスワードは「IDのパスワード」をSHAなんとかに通した値ということで。 IDは「種パスワード+なんとかのサイト」をSHAなんとかに通した値ということで。 種パスワードはしょうがないからネットをパスワードの決め方とかで検索して 出てきた方法を見て理解して自分なりにアレンジして、最後にちゃんと頭に記憶して。 とりあえずここまで、どうでしょうか。

  • ハッシュを使った擬似乱数

    予測不能な擬似乱数列を生成する際に、よく一方向ハッシュの性質を利用する 場合があります。一方向ハッシュの生成源として内部状態が与えられますが、 内部状態のbitサイズはどの程度にしたらよいでしょうか?   [種(カウンタの初期値)]        |        |        ↓ ┌→[内部状態(カウンタ)]―┬―→(一方向ハッシュ)――→擬似乱数列 |                 | |                 ↓ |               [1増加] |                 | └―――――――――――┘ ※ 暗号技術入門 秘密の国のアリス 結城 浩 著      ――第12章 乱数 Fig.12.5 より 極端な例として鍵(種)のサイズを32bit(C言語でunsigned long型)、値を0とします。 |0000 0000|0000 0000|0000 0000|0000 0000| 上記の値でハッシュ値を取ります。ハッシュアルゴリズムがSHA1の場合、 以下のような値が得られます(と思います)。 a = -1099956234 b = -343932961 c = -1287651379 d = -84150665 e = -1099170433 これらの値から鍵の値を得ることは困難なので、ハッシュ値によって生成された 擬似乱数は予測不能であるといえます。また、鍵の値を1だけ加算させて次の擬似乱数 を生成します。一般的にこのようにして乱数列は生成されます。 上記の例では32bitのとり得る値は0~4294967295です。鍵の値を一つずつ試し ていけば、それほど時間をかけることなく乱数の予測不能性は破られてしまいます。 ここで鍵の値を256bitとしました。 |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| しかしこれだと1加算しただけではビット全体に対して変化が少なすぎます。 |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0000| |0000 0000|0000 0000|0000 0000|0000 0001|← 2005年に中国の大学の研究チームによってSHA1の弱衝突耐性が破られてしまいました。 現段階ではSHA1に変わる新しいアルゴリズムは発見されていません。(SHA2が作られましたが、 これはSHA1のbit数を拡張しただけで基本設計は変わっていません)なのでハッシュ値を 生成させる値もなるべく変化に富んだ値を与えることが推奨されています。 まとめると、   ・鍵(種)を総当り攻撃されないようにbit数を大きくしなけらばならない。   ・bit数を大きくすると1加算したときに変化が小さすぎる。   ・最初の図の手法は同記の文献に書いてあったもので、なるべく変えたくない。    (実際に使われる手法はある程度保障されているから) の制約があります。なので”bit数をどの程度にしたら適当か???”というのが質問です。 また、これらの問題を打開する方法もあればよいのですが、、、

  • セキュリティ証明書のハッシュ値について

    セキュリティ証明書(SSL通信時などに利用する証明書)には 拇印情報があり、ここは証明書自身のハッシュ値が記録されていると聞きました。 証明書から作成されたハッシュ値を再びハッシュ値に記載したら 元の証明書を書き換えているため、次回ハッシュ値を求めたら別のハッシュ値になりませんか? 1.証明書 -> [ハッシュ関数] -> ハッシュ値 2.ハッシュ値を証明書に記述記載 3.証明書(ハッシュ値付き)-> [ハッシュ関数] -> ハッシュ値 1と3の結果のハッシュ値同士は一致しないですよね? GMailの証明書を見ると、sha1で、 90adbe01984695b6649ad0f9ef4f1b5836eb380d という値になっていて、 私の端末(WindowsXP)でfcivコマンドを実行した結果も fciv -sha1 gmail.cer 90adbe01984695b6649ad0f9ef4f1b5836eb380d gmail.cer となり、同じ値なのですが。。。 証明書に記載されているハッシュ値はどのように計算されているのでしょうか?

  • ハッシュで重複キーを認める方法について

    現在、Perlを用いてBootstrap法という方法論によるデータの加工を行っています。 その中でハッシュを使います。 それはkeyでsortしvalueを並び替え、その並び替えたvalueを処理することが目的です。  例えばこのようなものです。  Height  Weight   170.6  54.8   185.7  87.2   156.1  78.6   185.7  87.2   164.5  54.7   156.1  45.3    :     : 以上のようなデータに対し、Heightをkeyにsortし、Weightを並び替え、その並び替えたWeightの値を上から順に同数ずつ、複数のグループに分類することが目的です。 ですがハッシュでは重複keyはvalueが上書きされてしまうので、元のデータより少なくなってしまい正確なsort、並び替えができません。 Perlでこの重複を回避する方法を教えていただきたく思います。

    • ベストアンサー
    • Perl
  • パスワードのsaltの構築方法

    PHPでパスワードの登録でsaltを使用しようと考えているのですが、ネットで調べても自分の疑問に思っている事が出てきません。 パスワードにsaltという十分な長さ(40文字とか)の文字列を加え、それをmd5などでハッシュ化する・・・と言うことは分かりました。 しかしその実装方法が分かりません。 A.saltはランダム乱数でもいいし、セキュリティは低くなるが固定文字列でもいい。 B.saltは別ファイルに保管(一緒に保管と書いてあるのもありましたが)する。 、というような記事を見かけました。 で、自分はZendFrameworkのマニュアルに沿って考えたのですが、 データベーステーブルにpassword、saltカラムを作成する。 登録時、$_POST['ユーザの入力値']を(ハッシュ化する)passwordカラムに、saltはここでは単純にmt_rand(0,99)としてsaltカラムに登録、とした場合に認証時にはどのようにすればいいのでしょうか? 認証時にユーザの入力したパスワードとデータベースに格納したsaltを結合し、それをmd5()したものと、データベースに格納されているパスワードと同じく格納されたsaltを結合しそれをmd5()したものを比べる ・・・となるとパスワードさえ合って入ればいいので別にsaltは不要なような気がするのでこの実装法は間違っているのかなと思います。 そうではなく、登録時にユーザの入力したパスワードとデータベースに格納したsaltを結合し、それをmd5()したものをpasswordカラム又はsaltカラムに格納する・・・というのも正しいのかな?と思います。 データベースに侵入されればどちらもダメなので、何か別ファイルに保管するのかなとも思いましたが良く分かりません。 登録フォーム => ログインフォームにおいてのsaltの実装法を教えていただけないでしょうか?少し頭がぐちゃぐちゃになり、ちょっと文章がおかしい気もしますがすみません。

    • ベストアンサー
    • PHP
  • ストレッチング

    こんにちは。 今日、パスワードに関する記事を読みました。 パスワードというのは平文で保存しないで、代わりにハッシュ関数を施した値を保存して、これらの値が漏えいしても元のパスワードが解読されないようにしているみたいです。そして「ストレッチング」というのは、このハッシュ計算を何回も施した値を保存するのだそうです。 そこで、質問です: パスワードの保護に関して「十分に安全なハッシュ計算」(そういうモノがあるとして)の冪乗は、再び「十分に安全なハッシュ計算」になるのでしょうか。 よろしくお願いします。

  • Perlでモジュールをインストールしない方法

    Perlでモジュールをインストールしない方法をしりたいです。 普通はコマンドを使ったりして必要なモジュールを予めインストールしますが、インストールせずにCPANサイトからモジュールをダウンロードしてきて使用する方法はありますか? 自分の感覚だと、プログラムの最初に何かを宣言すればいいのかな、と思うのですが。

    • ベストアンサー
    • Perl
  • VLOOKUP関数について質問です!困ってます(>_<)

    VLOOKUP関数について質問です!困ってます(>_<) VLOOKUP関数を使用して下記のようなことをやりたいのですが、方法が思いつきません。 マクロの知識もなく、できれば関数でなんとかしたいところです。 どなたかお分かりになられる方がいらっしゃいましたらお願いいたします! 規定フォーマットに「01(注文番号)」と打ち込むと、別シートにあるデータ中から「01」に関する情報が自動的に規定フォーマットに入力されるという仕組みを考え中です。 ※シート1には規定フォーマット、シート2には別データがあり。 VLOOKUP関数を使用すると、指定した列に同じ答えが複数ある場合に正確な値が抽出できません。 規定フォーマットにはStep1~4まで項目があり、Step1は該当するうちの一番上の値、Step2は二番目の値・・としたいため、「01に該当する値のうち、一番上の値を抜き出せ」という式を完成させたいですこの式が出来れば、Step1~4までのそれぞれ「01」に該当する値を抽出することができる気がします。 ※基本式がわかればなんとかなりそうです。ご教授お願いいたします。 ※別表データ内容は注文番号含め毎年変わるため、フォーマット上に関数を設定してます。 規定フォーマットは毎年固定です。別データでオートフィルタの使用はせず、そして列等挿入しない(加工しない)方向でかんがえています。毎年データを加工するのが面倒なので、関数だけでのりきりたいです。 別に表を作るのもだめだと上司に言われました(>_<) データ入手後、表に毎年同じ名前をつけて使用すれば、関数でなんとかなるのではと思っています。 行数は変わっても列数は毎年変わらないので。 《例》 シート1:        注文番号(01)←ここ手入力                 STEP1(CCDD) ⇒ 自動入力にしたい STEP2(CCAA) STEP3(CCzz) STEP4(CCss)                          シート2: 01/CCDD ※一番上にある値はSTEP1とする 01/CCAA ※二番目にある値はSTEP2とする 01/CCzz ※三番目にある値はSTEP3とする 01/CCss ※四番目にある値はSTEP4とする 02/eeoo ※STEP1とする 03/jjhh ※STEP1とする 03/kkoo ※STEP2とする        内容が複雑なのでどう表現したらいいかわからず、上手く伝えられない のが大変申し訳ないです。 どなたかお力をお貸し下さい!! 宜しくお願いいたします。

専門家に質問してみよう