MySQLへのSHA1ハッシュ値の保存


160

SHA1ハッシュの結果をMySQLデータベースに保存したいときに発生した簡単な質問があります。

ハッシュの結果を格納するVARCHARフィールドはどのくらいの期間必要ですか?


9
sha1をググっただけでラッキーな気分になり、ウィキペディアにアクセスすると、常に160ビットであることがわかります。
Tim Matthews

回答:


315

VARCHAR可変長データに使用しますが、固定長データには使用しません。SHA-1値は常に 160ビット長であるため、固定長フィールドの長さのために追加のバイトがVARCHAR無駄になるだけです。

また、返される値も保存しませんSHA1。文字あたり4ビットしか使用しないため、160/4 = 40文字が必要になるためです。ただし、1文字あたり8ビットを使用する場合、必要なのは160/8 = 20文字の長さのフィールドだけです。

使用することをお勧めします私はそうBINARY(20)UNHEX機能変換するために、SHA1バイナリに値を。

とのストレージ要件を比較BINARY(20)しましたCHAR(40)

CREATE TABLE `binary` (
    `id` int unsigned auto_increment primary key,
    `password` binary(20) not null
);
CREATE TABLE `char` (
    `id` int unsigned auto_increment primary key,
    `password` char(40) not null
);

何百万ものレコードbinary(20)があると、44.56M char(40)かかりますが、64.57Mかかります。 InnoDBエンジン。


2
PostgreSQLでは、これはbyteaフィールドを使用することになりますよね?
mvexel 2011年

解決策は素晴らしいですが、16進数のsha1でchar(40)を使用する別のポイントがあります。これははるかに広く使用されており、アプリケーションコードでの変換の問題が少なくなります。
アーサークッシュマン'09

2
phpmyadminユーザー向けの注意。ハッシュをバイナリとして保存すると、phpmyadminはそれを16進文字列として表示しますが、pmaは提供された「検索タブ」でそれを使用できません。UNHEX()手動でSQLに追加した場合にのみ機能します。
Timo Huovinen、2014年

2
@Gumbo byteaに可変数のバイトを格納できます。byteaタイプのストレージ要件を参照しています。これは、「1または4バイトと実際のバイナリ文字列」です。varcharの場合のようにゼロバイトを使用して文字列を終了することはできないため、「1または4」が指すのは格納されているデータの長さである可能性があります。つまり、マニュアルには明記されていませんが、byteaには最大2 ^(8 * 4)または4+ギガバイトを格納できます。postgresql.org/docs/9.0/static/datatype-binary.html ハッシュをpostgresデータベースに格納することは、おそらくビット列またはbytea列として最小です。
Viktor

2
dev.mysql.com/doc/refman/5.5/en/…は、crypt関数の結果を保存する際のパフォーマンスとストレージに関する情報を提供します
Clocker


11

このブログから引用したリファレンス:

以下は、ハッシュアルゴリズムと必要なビットサイズのリストです。

  • MD5 = 128ビットのハッシュ値。
  • SHA1 = 160ビットのハッシュ値。
  • SHA224 = 224ビットのハッシュ値。
  • SHA256 = 256ビットのハッシュ値。
  • SHA3​​84 = 384ビットのハッシュ値。
  • SHA512 = 512ビットのハッシュ値。

require CHAR(n)で1つのサンプルテーブルを作成しました:

CREATE TABLE tbl_PasswordDataType
(
    ID INTEGER
    ,MD5_128_bit CHAR(32)
    ,SHA_160_bit CHAR(40)
    ,SHA_224_bit CHAR(56)
    ,SHA_256_bit CHAR(64)
    ,SHA_384_bit CHAR(96)
    ,SHA_512_bit CHAR(128)
); 
INSERT INTO tbl_PasswordDataType
VALUES 
(
    1
    ,MD5('SamplePass_WithAddedSalt')
    ,SHA1('SamplePass_WithAddedSalt')
    ,SHA2('SamplePass_WithAddedSalt',224)
    ,SHA2('SamplePass_WithAddedSalt',256)
    ,SHA2('SamplePass_WithAddedSalt',384)
    ,SHA2('SamplePass_WithAddedSalt',512)
);

10
、してくださいしてくださいしてください、実際にこのようなパスワードを保管しないでください。
ベリーM.

ちょっとベリー、なぜあなたの理由を説明できますか?詳細
Anvesh 2017

4
単純なパスワードのハッシュを保存すると、ソルトされた(うまくいけば)ハッシュされたパスワードハッシュを使用するよりも、データベースが危険にさらされている場合に、パスワードが「抽出」されやすくなります。推奨読書:paragonie.com/blog/2016/02/how-safely-store-password-in-2016
マット

2
@BerryM。1年後にこれを読んでいて、誰もがパスワードについて話しているとか、人々がまだ単純なハッシュを使用して認証データを保存しているとか、一瞬も思っていませんでした。しかし、彼らはそうします:D
Rohit Hazra

6

sha1の出力サイズは160ビットです。160/8 == 20文字(8ビット文字を使用する場合)または160/16 = 10(16ビット文字を使用する場合)です。


8ビットのバイナリ文字を想定しています。16進数として保存した場合は40文字。
Tyzoid 2013

3

したがって、長さは10個の16ビット文字と40個の16進数の間です。

いずれにしても、保存するフォーマットを決定し、そのフォーマットに基づいてフィールドを固定サイズにします。そうすれば、無駄なスペースがなくなります。


2

ユーザーのハッシュを常に保存するとは限らない場合(つまり、アカウントの認証/ログインURLを忘れた場合)には、VARCHARを使用することもできます。ユーザーがログイン情報を認証または変更すると、ハッシュを使用できなくなり、理由もなくなります。一時的なハッシュを格納する別のテーブルを作成することもできます->削除できるユーザーの関連付けですが、ほとんどの人がこれを行う必要はないと思います。


2

sha1列のインデックスが必要な場合は、パフォーマンス上の理由からCHAR(40)をお勧めします。私の場合、sha1列は電子メールの確認トークンなので、ランディングページでは、クエリはトークンのみで入力します。この場合、私の考えでは、INDEXを指定したCHAR(40)が最良の選択です。

この方法を採用する場合は、$ raw_output = falseのままにしてください。


1
BINARY(20)にインデックスを付けないのはなぜですか?それは同じくらい速く、半分の大きさではないでしょうか?
nickdnk 2017

まあこれは約5年前ですが、まだ負荷を追加するunhexを行う必要があるという事実を参照していたと思います(+により、アプリケーションの維持が難しくなり、移植性が低下しますか?)。それはちょっとハードウェアにも依存します。もしストレージが少なくて遅い場合は、おそらくバイナリ(20)を使用するのが最善です。それ以外の場合は、チャー(40)と言います。使用する言語とハードウェアでいくつかのテストを実行せずに言うのは難しいですし、自分に最適なものを確認してください。
Francesco Casula 2017

1
unhex(hash)= hashから選択して単一の行をフェッチする以外のことをしている場合は、おそらくあなたは正しいと思います。ただし、この方法では、インデックスをバッファリングしておくと、メモリが2倍になります。
nickdnk 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.