Menyimpan nilai hash SHA1 di MySQL

160

Saya punya pertanyaan sederhana yang muncul ketika saya ingin menyimpan hasil hash SHA1 dalam database MySQL:

Berapa lama bidang VARCHAR berada di tempat saya menyimpan hasil hash?

niklasfi
sumber
9
Jika Anda hanya googled sha1 klik im merasa beruntung dan Anda harus berada di wikipedia di mana Anda dapat menemukannya selalu 160 bit.
Tim Matthews

Jawaban:

315

Saya akan menggunakan VARCHARuntuk data panjang variabel, tetapi tidak dengan data panjang tetap. Karena nilai SHA-1 selalu panjang 160 bit, VARCHARhanya akan membuang byte tambahan untuk panjang bidang panjang tetap .

Dan saya juga tidak akan menyimpan nilai yang SHA1dikembalikan. Karena hanya menggunakan 4 bit per karakter dan dengan demikian akan membutuhkan 160/4 = 40 karakter. Tetapi jika Anda menggunakan 8 bit per karakter, Anda hanya perlu bidang 160/8 = 20 karakter.

Jadi saya sarankan Anda untuk menggunakan BINARY(20)dan UNHEXfungsinya untuk mengubah SHA1nilai menjadi biner.

Saya membandingkan persyaratan penyimpanan untuk BINARY(20)dan 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
);

Dengan jutaan catatan, binary(20)dibutuhkan 44,56 juta, sementara char(40)64,57 juta. InnoDBmesin.

Gumbo
sumber
2
Di PostgreSQL, ini akan diterjemahkan menggunakan bidang bytea, kan?
mvexel
Solusinya bagus, tetapi ada titik lain untuk menggunakan char (40) dengan hexed sha1 - ini jauh lebih banyak digunakan, dan akan ada lebih sedikit masalah konversi dalam kode aplikasi.
Arthur Kushman
2
Catatan untuk pengguna phpmyadmin. Saat menyimpan hash sebagai biner, phpmyadmin akan menampilkannya sebagai string hex, tetapi pma tidak akan dapat menggunakannya di "tab pencarian" yang disediakan. Hanya akan berfungsi jika Anda menambahkan UNHEX()secara manual ke sql.
Timo Huovinen
2
@ Gumbo Anda dapat menyimpan jumlah byte dalam variabel dalam bytea. Anda mengacu pada persyaratan penyimpanan jenis bytea. Yaitu "1 atau 4 byte plus string biner yang sebenarnya". Yang dimaksud dengan "1 atau 4" bisa menjadi panjang data yang disimpan, karena Anda tidak dapat menggunakan byte nol untuk mengakhiri string seperti yang Anda lakukan dengan varchar. Itu menyiratkan, tetapi tidak dinyatakan dalam manual, bahwa Anda dapat menyimpan hingga 2 ^ (8 * 4) atau 4+ gigabytes dalam bytea. postgresql.org/docs/9.0/static/datatype-binary.html Menyimpan hash dalam database postgres mungkin akan menjadi terkecil sebagai bit atau bytea kolom.
Viktor
2
dev.mysql.com/doc/refman/5.5/en/… menyediakan info tentang kinerja dan penyimpanan saat menyimpan hasil fungsi crypt
Clocker
45

Panjang hash SHA1 adalah 40 karakter!

schmilblick
sumber
11

Referensi diambil dari blog ini:

Di bawah ini adalah daftar algoritma hashing beserta ukuran bit yang dibutuhkan:

  • MD5 = 128-bit nilai hash.
  • SHA1 = nilai hash 160-bit.
  • SHA224 = nilai hash 224-bit.
  • SHA256 = Nilai hash 256-bit.
  • SHA384 = Nilai hash 384-bit.
  • SHA512 = nilai hash 512-bit.

Dibuat satu tabel sampel dengan membutuhkan CHAR (n):

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)
);
Landasan
sumber
10
Tolong, tolong , tolong jangan benar-benar menyimpan kata sandi seperti ini.
Berry M.
Hai beri, bisakah Anda menjelaskan MENGAPA? dalam rincian
Anvesh
4
Menyimpan hash kata sandi yang sederhana membuat kata sandi lebih mudah "diekstraksi" jika basis data Anda dikompromikan daripada jika Anda menggunakan hash kata sandi asin (semoga diperluas). Bacaan yang disarankan: paragonie.com/blog/2016/02/how-safely-store-password-in-2016
matt
2
@BerryM. membaca ini setahun kemudian, dan tidak berpikir sejenak bahwa ada yang berbicara tentang kata sandi atau bahwa jika orang masih menggunakan hash sederhana untuk menyimpan data auth. Tetapi mereka melakukannya: D
Rohit Hazra
6

Ukuran output dari sha1 adalah 160 bit. Yaitu 160/8 == 20 karakter (jika Anda menggunakan karakter 8-bit) atau 160/16 = 10 (jika Anda menggunakan karakter 16-bit).

inazaruk
sumber
Dengan asumsi karakter biner 8-bit. 40 karakter jika disimpan sebagai hex.
Tyzoid
3

Jadi panjangnya antara 10 karakter 16-bit, dan 40 digit hex.

Dalam kasus apa pun, tentukan format yang akan Anda simpan, dan jadikan bidang itu ukuran tetap berdasarkan format itu. Dengan begitu Anda tidak akan memiliki ruang kosong.

Douglas Leeder
sumber
2

Anda mungkin masih ingin menggunakan VARCHAR dalam kasus di mana Anda tidak selalu menyimpan hash untuk pengguna (yaitu mengautentikasi akun / lupa url login). Setelah pengguna mengautentikasi / mengubah info masuk mereka, mereka seharusnya tidak dapat menggunakan hash dan seharusnya tidak punya alasan untuk itu. Anda dapat membuat tabel terpisah untuk menyimpan hash -> asosiasi pengguna sementara yang dapat dihapus tapi saya rasa kebanyakan orang tidak repot-repot melakukan ini.

Keith Harty
sumber
2

Jika Anda memerlukan indeks pada kolom sha1, saya sarankan CHAR (40) karena alasan kinerja. Dalam kasus saya, kolom sha1 adalah token konfirmasi email, jadi pada halaman landing kueri hanya masuk dengan token. Dalam hal ini CHAR (40) dengan INDEX, menurut pendapat saya, adalah pilihan terbaik :)

Jika Anda ingin mengadopsi metode ini, jangan lupa untuk meninggalkan $ raw_output = false.

Francesco Casula
sumber
1
Mengapa Anda tidak mengindeks BINARY (20)? Bukankah itu secepat dan setengah dari ukurannya?
nickdnk
Nah ini ~ 5 tahun yang lalu tapi saya pikir saya merujuk pada fakta bahwa Anda masih perlu unhex yang menambahkan beberapa beban (+ membuat aplikasi lebih sulit untuk dirawat dan kurang portabel?). Ini agak tergantung pada perangkat keras Anda juga, jika Anda mendapat lebih sedikit penyimpanan dan lambat juga mungkin lebih baik untuk tetap pada biner (20) kalau tidak saya akan mengatakan char (40). Sulit dikatakan tanpa menjalankan beberapa tes dengan bahasa dan perangkat keras yang akan Anda gunakan dan melihat yang paling cocok untuk Anda.
Francesco Casula
1
Saya kira jika Anda melakukan sesuatu selain memilih dari mana unhex (hash) = hash untuk mengambil satu baris, maka mungkin Anda benar. Tetapi menjaga buffer indeks akan mengambil memori dua kali lebih banyak dengan cara ini.
nickdnk