การเก็บค่าแฮช SHA1 ใน MySQL


160

ฉันมีคำถามง่าย ๆ ที่เกิดขึ้นเมื่อฉันต้องการเก็บผลลัพธ์ของการแฮช SHA1 ในฐานข้อมูล MySQL:

นานแค่ไหนที่ควรVARCHARข้อมูลจะอยู่ในที่ฉันเก็บผลกัญชาหรือไม่


9
หากคุณเพิ่งเริ่มใช้ sha1 คลิกฉันรู้สึกโชคดีและคุณควรจะอยู่ในวิกิพีเดียที่คุณสามารถค้นหาได้เสมอ 160 บิต
ทิมแมตทิวส์

คำตอบ:


315

ฉันจะใช้VARCHARสำหรับข้อมูลความยาวผันแปรได้ แต่ไม่ใช่ข้อมูลความยาวคงที่ เพราะค่า SHA-1 เป็นเสมอ 160 บิตนานVARCHARก็จะเสียไบต์เพิ่มเติมสำหรับความยาวของสนามคงยาว

และฉันก็จะไม่เก็บค่าที่SHA1จะกลับมา เพราะมันใช้เพียง 4 บิตต่อตัวละครดังนั้นจะต้องมี 160/4 = 40 ตัวอักษร แต่ถ้าคุณใช้ 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.56 ล้านขณะที่char(40)ใช้เวลา 64.57 ล้าน InnoDBเครื่องยนต์


2
ใน PostgreSQL สิ่งนี้จะแปลเป็นการใช้ฟิลด์ bytea ใช่ไหม
mvexel

วิธีแก้ปัญหานั้นยอดเยี่ยม แต่มีอีกจุดหนึ่งที่ใช้ char (40) กับ hexed sha1 - ซึ่งมีการใช้กันอย่างแพร่หลายและจะมีปัญหาการแปลงในรหัสแอปพลิเคชัน
Arthur Kushman

2
หมายเหตุสำหรับผู้ใช้ phpmyadmin เมื่อจัดเก็บแฮชเป็นไบนารี phpmyadmin จะแสดงสตริงนั้นเป็นสตริงฐานสิบหก แต่ pma จะไม่สามารถใช้งานได้ใน "แท็บค้นหา" ที่ให้มา จะทำงานเฉพาะในกรณีที่คุณเพิ่มUNHEX()sql ด้วยตนเอง
Timo Huovinen

2
@Gumbo คุณสามารถเก็บจำนวนตัวแปรไบต์ในไบต์ คุณกำลังอ้างถึงข้อกำหนดการจัดเก็บของประเภท bytea ซึ่งคือ "1 หรือ 4 ไบต์บวกกับสตริงไบนารีจริง" สิ่งที่ "1 หรือ 4" หมายถึงอาจเป็นความยาวของข้อมูลที่เก็บไว้เนื่องจากคุณไม่สามารถใช้ศูนย์ไบต์เพื่อสิ้นสุดสตริงเช่นเดียวกับที่คุณทำกับ varchar แต่ไม่ได้ระบุไว้ในคู่มือคุณสามารถจัดเก็บได้สูงสุด 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 บิต
  • SHA384 = ค่าแฮช 384 บิต
  • SHA512 = ค่าแฮช 512 บิต

สร้างตารางตัวอย่างหนึ่งตารางโดยต้องการ 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)
);

10
กรุณาโปรด , โปรดไม่จริงเก็บรหัสผ่านเช่นนี้
Berry M.

เฮ้เบอรี่คุณช่วยอธิบายเหตุผลของคุณได้อย่างไร ในรายละเอียด
Anvesh

4
การจัดเก็บแฮชของรหัสผ่านอย่างง่ายจะทำให้การ "แยก" รหัสผ่านง่ายขึ้นถ้าฐานข้อมูลของคุณถูกบุกรุกมากกว่าถ้าคุณใช้แฮชรหัสผ่านแบบเค็ม การอ่านที่แนะนำ: paragonie.com/blog/2016/02/how-safely-store-password-in-2016
matt

2
@BerryM อ่านสิ่งนี้ในอีกหนึ่งปีต่อมาและไม่คิดว่าจะมีใครพูดถึงรหัสผ่านหรือถ้าคนยังคงใช้แฮชธรรมดาเพื่อเก็บข้อมูลรับรองความถูกต้อง แต่พวกเขาทำ: D
Rohit Hazra

6

ขนาดเอาต์พุตของ sha1 คือ 160 บิต ตัวไหนคือ 160/8 == 20 ตัวอักษร (ถ้าคุณใช้ 8-bit chars) หรือ 160/16 = 10 (ถ้าคุณใช้ 16-bit chars)


สมมติว่าอักขระไบนารี 8 บิต 40 ตัวอักษรหากเก็บไว้เป็นเลขฐานสิบหก
Tyzoid

3

ดังนั้นความยาวจึงอยู่ระหว่าง 10 16- บิตตัวอักษรและ 40 ฐานสิบหก

ไม่ว่าในกรณีใดให้เลือกรูปแบบที่คุณกำลังจะจัดเก็บและทำให้ฟิลด์มีขนาดคงที่ตามรูปแบบนั้น ด้วยวิธีนี้คุณจะไม่มีพื้นที่ว่างเปล่า


2

คุณอาจยังต้องการใช้ VARCHAR ในกรณีที่คุณไม่ได้เก็บแฮชไว้สำหรับผู้ใช้เสมอ (เช่นการตรวจสอบสิทธิ์บัญชี / ลืม URL ล็อกอิน) เมื่อผู้ใช้รับรองความถูกต้อง / เปลี่ยนข้อมูลการเข้าสู่ระบบพวกเขาไม่ควรใช้แฮชและไม่ควรมีเหตุผล คุณสามารถสร้างตารางแยกต่างหากเพื่อเก็บแฮชชั่วคราว -> การเชื่อมโยงผู้ใช้ที่สามารถลบได้ แต่ฉันไม่คิดว่าคนส่วนใหญ่จะสนใจที่จะทำสิ่งนี้


2

หากคุณต้องการดัชนีในคอลัมน์ sha1 ฉันแนะนำ CHAR (40) ด้วยเหตุผลด้านประสิทธิภาพ ในกรณีของฉันคอลัมน์ sha1 เป็นโทเค็นการยืนยันทางอีเมลดังนั้นในหน้า Landing Page แบบสอบถามจะเข้าสู่โทเค็นเท่านั้น ในกรณีนี้ CHAR (40) กับ INDEX ในความคิดของฉันเป็นตัวเลือกที่ดีที่สุด :)

หากคุณต้องการใช้วิธีนี้อย่าลืมปล่อยให้ $ raw_output = false


1
ทำไมคุณไม่สร้างดัชนีไบนารี (20) จะเร็วขนาดนี้หรือจะใหญ่กว่าครึ่งหรือไม่?
nickdnk

อย่างนี้ ~ 5 ปีก่อน แต่ฉันคิดว่าฉันหมายถึงความจริงที่ว่าคุณยังต้องไม่ปลอดภัยซึ่งเพิ่มภาระบางอย่าง (+ ทำให้แอปพลิเคชันยากต่อการดูแลรักษาและพกพาได้น้อยลง) มันขึ้นอยู่กับฮาร์ดแวร์ของคุณเช่นกันถ้าคุณมีพื้นที่เก็บข้อมูลน้อยกว่าและมันก็อาจจะดีที่สุดถ้าคุณติดกับเลขฐานสอง (20) ไม่อย่างนั้นฉันจะพูดว่า char (40) ยากที่จะพูดโดยไม่ทำการทดสอบภาษาและฮาร์ดแวร์ที่คุณใช้และดูว่าอะไรเหมาะสมกับคุณที่สุด
Francesco Casula

1
ฉันคิดว่าถ้าคุณกำลังทำสิ่งอื่นนอกเหนือจากการเลือกจากที่ unhex (hash) = hash เพื่อดึงข้อมูลแถวเดียวบางทีคุณอาจพูดถูก แต่การเก็บดัชนีบัฟเฟอร์จะใช้หน่วยความจำมากเป็นสองเท่าด้วยวิธีนี้
nickdnk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.