ฟังก์ชันแฮชที่ดีคืออะไร


130

ฟังก์ชันแฮชที่ดีคืออะไร ฉันเห็นฟังก์ชันแฮชและแอปพลิเคชันจำนวนมากในหลักสูตรโครงสร้างข้อมูลในวิทยาลัย แต่ส่วนใหญ่ฉันเข้าใจว่ามันยากที่จะสร้างฟังก์ชันแฮชที่ดี ตามกฎของหัวแม่มือเพื่อหลีกเลี่ยงการชนศาสตราจารย์ของฉันกล่าวว่า:

function Hash(key)
  return key mod PrimeNumber
end

(mod คือตัวดำเนินการ% ในภาษา C และภาษาที่คล้ายคลึงกัน)

โดยมีหมายเลขเฉพาะเป็นขนาดของตารางแฮช ฉันได้รับมันเป็นฟังก์ชั่นที่ค่อนข้างดีในการหลีกเลี่ยงการชนและสิ่งที่รวดเร็ว แต่ฉันจะทำให้ดีขึ้นได้อย่างไร มีฟังก์ชันแฮชที่ดีกว่าสำหรับปุ่มสตริงเทียบกับคีย์ตัวเลขหรือไม่?


34
คุณได้พิจารณาใช้ฟังก์ชันแฮชวัตถุประสงค์ทั่วไปต่อไปนี้อย่างน้อยหนึ่งอย่างแล้วหรือไม่: partow.net/programming/hashfunctions/index.html

ใน fnv_func ชนิดของ p [i] คือ char จะเกิดอะไรขึ้นกับ h หลังจากการทำซ้ำครั้งแรก มันตั้งใจทำหรือไม่?

5
@martinatime กล่าวว่า: มีข้อมูลมากมายเกี่ยวกับฟังก์ชันแฮชใน wikipedia en.wikipedia.org/wiki/Hash_functionและด้านล่างของบทความนี้partow.net/programming/hashfunctions/index.htmlมีอัลกอริทึมที่ใช้ในภาษาต่างๆ
2501

คำตอบ:


33

สำหรับการค้นหาตารางแฮชแบบ "ปกติ" บนพื้นฐานของข้อมูลชนิดใด - อันนี้โดย Paul Hsieh นั้นดีที่สุดที่ฉันเคยใช้

http://www.azillionmonkeys.com/qed/hash.html

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


ขอบคุณสำหรับลิงค์ข้อมูล! ฉันรู้ว่าการวิเคราะห์บางอย่างโดย Bob Jenkins และคนอื่น ๆ ซึ่งชี้ไปที่ฟังก์ชันแฮชที่เป็นที่ยอมรับในระดับสากล แต่ฉันยังไม่ได้เจอ
Konrad Rudolph

ฉันได้อ่านจากเว็บไซต์ของเจนกินส์ที่ SFH เป็นหนึ่งในดีที่สุดแล้ว แต่ฉันคิดว่า Murmur อาจทำได้ดีกว่าดูคำตอบที่ยอดเยี่ยมนี้: programmers.stackexchange.com/questions/49550/…
nawfal

2
YMMV หมายถึงอะไร
cobarzan

3
@cobarzan Your Mileage อาจแตกต่างกัน
ProgrammerDan

2
ฟังก์ชั่นแฮชของ Hsieh นั้นแย่มากโดยมีลำดับความสำคัญมากกว่าที่เราต้องการ โดยเฉพาะอย่างยิ่งสตริงที่แตกต่างกันเฉพาะใน 4 ไบต์สุดท้ายสามารถชนกันได้อย่างง่ายดาย หากคุณมีสตริงอักขระ 30 ตัวซึ่งแตกต่างกันใน 4 ไบต์สุดท้ายหลังจาก 28 ไบต์ได้รับการประมวลผลแฮชจะแตกต่างกันใน 2 ไบต์สุดท้ายเท่านั้น นั่นหมายความว่าคุณจะรับประกันการชนกันของค่าสองไบต์ที่เหลือ (ใช่มันเร็วมากดังนั้นอะไร)
แอนดรูลาซารัส

51

ไม่มีฟังก์ชั่น "hash function ที่ดี" สำหรับ hash universal (ed. ใช่ฉันรู้ว่ามี "hash universal" แต่นั่นไม่ใช่สิ่งที่ฉันหมายถึง) ขึ้นอยู่กับบริบทเกณฑ์ที่แตกต่างกันกำหนดคุณภาพของแฮ คนสองคนพูดถึง SHA แล้ว นี่เป็นแฮชการเข้ารหัสลับและมันก็ไม่ได้ดีสำหรับตารางแฮชที่คุณอาจหมายถึง

ตารางแฮชมีข้อกำหนดที่แตกต่างกันมาก แต่ถึงกระนั้นการค้นหาฟังก์ชันแฮชที่ดีในระดับสากลนั้นเป็นเรื่องยากเพราะประเภทข้อมูลที่แตกต่างกันจะเปิดเผยข้อมูลที่แตกต่างกันซึ่งสามารถแฮชได้ เป็นกฎง่ายๆที่ดีในการพิจารณาข้อมูลทั้งหมดประเภทถืออย่างเท่าเทียมกัน นี่ไม่ใช่เรื่องง่ายหรือเป็นไปได้เสมอไป สำหรับเหตุผลของสถิติ (และการชนกันของข้อมูล) สิ่งสำคัญคือการสร้างการแพร่กระจายที่ดีในพื้นที่ปัญหาเช่นวัตถุที่เป็นไปได้ทั้งหมด ซึ่งหมายความว่าเมื่อ hashing ตัวเลขระหว่าง 100 และ 1,050 ไม่ดีที่จะให้ตัวเลขที่สำคัญที่สุดเล่นเป็นส่วนใหญ่ในแฮชเพราะประมาณ 90% ของวัตถุตัวเลขนี้จะเป็น 0 มันสำคัญยิ่งกว่าที่จะให้สามครั้งสุดท้าย หลักกำหนดแฮ

ในทำนองเดียวกันเมื่อ hashing สตริงเป็นสิ่งสำคัญที่จะต้องพิจารณาตัวละครทั้งหมด - ยกเว้นเมื่อเป็นที่รู้จักกันล่วงหน้าว่าตัวละครสามตัวแรกของสตริงทั้งหมดจะเหมือนกัน; การพิจารณาสิ่งเหล่านี้เป็นของเสีย

นี่เป็นหนึ่งในกรณีที่ฉันแนะนำให้อ่านสิ่งที่ Knuth พูดในThe Art of Computer Programming , vol. 3. อ่านที่ดีก็คือ Julienne วอล์คเกอร์ศิลปะของ Hashing


1
คอนราดคุณถูกต้องจากมุมมองทางทฤษฎี แต่คุณเคยลองใช้ฟังก์ชันแฮช Paul Hsieh ที่ฉันพูดถึงในความคิดเห็นของฉันหรือไม่? มันค่อนข้างดีกับข้อมูลชนิดต่าง ๆ มากมาย!
คริสแฮร์ริส

9

มีวัตถุประสงค์หลักสองประการของฟังก์ชันการแฮช:

  • เพื่อกระจายจุดข้อมูลอย่างสม่ำเสมอเป็นบิต n
  • เพื่อระบุข้อมูลอินพุตอย่างปลอดภัย

เป็นไปไม่ได้ที่จะแนะนำแฮชโดยไม่ทราบว่าคุณกำลังใช้อะไรอยู่

หากคุณเพียงแค่สร้างตารางแฮชในโปรแกรมคุณไม่จำเป็นต้องกังวลว่าอัลกอริทึมที่สามารถย้อนกลับหรือแฮกได้คือ ... SHA-1 หรือ AES ไม่จำเป็นอย่างสมบูรณ์สำหรับเรื่องนี้รูปแบบของ FNV FNV ประสบความสำเร็จในการกระจายตัวที่ดีขึ้น (และลดการชนกัน) น้อยกว่า mod prime ที่เรียบง่ายอย่างที่คุณพูดถึง

หากคุณใช้แฮชในการซ่อนและตรวจสอบข้อมูลสาธารณะ (เช่นการแฮชรหัสผ่านหรือเอกสาร) คุณควรใช้อัลกอริทึมการแฮชที่สำคัญข้อใดข้อหนึ่งที่ได้รับการตรวจสอบโดยสาธารณะ เลานจ์ Hash Functionเป็นจุดเริ่มต้นที่ดี


อัปเดตลิงก์ไปยัง The Hash Function Lounge: larc.usp.br/~pbarreto/hflounge.html
Tim Partridge

FNV ทนต่อการชนกันของวันเกิดได้ดีเพียงใดเมื่อเปรียบเทียบกับจำนวนบิตเดียวกันกับ SHA1
Kevin Hsu

@Kevin ตราบใดที่ลักษณะของ avalanch ของ hash นั้นดี (การเปลี่ยนแปลงเล็ก ๆ ในอินพุต = การเปลี่ยนแปลงใหญ่ในเอาต์พุต) ดังนั้นการชนวันเกิดเป็นเพียงฟังก์ชันของบิตในแฮช FNV-1a นั้นยอดเยี่ยมในเรื่องนี้และคุณสามารถมีแฮชบิตได้มากหรือน้อยตามที่คุณต้องการ
Myrddin Emrys

5

นี่เป็นตัวอย่างของตัวอย่างที่ดีและเป็นตัวอย่างของสาเหตุที่คุณไม่ต้องการเขียน มันเป็น Fowler / Noll / Vo (FNV) แฮชซึ่งเป็นวิทยาศาสตร์คอมพิวเตอร์ที่เท่าเทียมกันและอัจฉริยะของวูดู:

unsigned fnv_hash_1a_32 ( void *key, int len ) {
    unsigned char *p = key;
    unsigned h = 0x811c9dc5;
    int i;

    for ( i = 0; i < len; i++ )
      h = ( h ^ p[i] ) * 0x01000193;

   return h;
}

unsigned long long fnv_hash_1a_64 ( void *key, int len ) {
    unsigned char *p = key;
    unsigned long long h = 0xcbf29ce484222325ULL;
    int i;

    for ( i = 0; i < len; i++ )
      h = ( h ^ p[i] ) * 0x100000001b3ULL;

   return h;
}

แก้ไข:

  • Landon Curt Noll แนะนำบนเว็บไซต์ของเขาอัลกอริทึม FVN-1A เหนืออัลกอริทึม FVN-1 ดั้งเดิม: อัลกอริทึมที่ได้รับการปรับปรุงให้ดีขึ้นดีกว่าการกระจายไบต์สุดท้ายในแฮช ฉันปรับอัลกอริทึมตามนั้น

3
คุณอาจต้องการดูข้อมูลบางส่วนเกี่ยวกับสาเหตุที่เลือกค่าเหล่านี้: isthe.com/chongo/tech/comp/fnv/#fnv-prime
Cthutu

อวยพรคุณ ฟังก์ชันแฮชแบบสั้นที่เรียบง่ายมีประสิทธิภาพสามัญและมีประสิทธิภาพนี้เป็นสิ่งที่ฉันต้องการ
mattarod

3

ฉันจะบอกว่ากฎหลักง่ายๆก็คือคุณจะต้องไม่กลิ้งตัวเอง ลองใช้สิ่งที่ผ่านการทดสอบอย่างละเอียดแล้วเช่น SHA-1 หรือบางสิ่งบางอย่างตามสายเหล่านั้น


ดูเหมือนว่าเขาไม่ต้องการอะไรที่ปลอดภัยด้วยการเข้ารหัสดังนั้น SHA-1 จึงเกินความเป็นจริง
Erik

ถึงแม้ว่าจะไม่พบการชนกันของ SHA-1 แต่เชื่อว่าจะเป็นเรื่องของปีหรือหลายเดือนก่อนที่จะพบใคร ฉันจะแนะนำโดยใช้ SHA-256
ซามูเอลอัลลัน

1

ฟังก์ชันแฮชที่ดีมีคุณสมบัติดังต่อไปนี้:

  1. เมื่อแฮชของข้อความเป็นไปไม่ได้ที่ผู้โจมตีจะค้นหาข้อความอื่น ๆ เพื่อให้แฮชเหมือนกัน

  2. เมื่อได้รับข้อความคู่ m และ m มันเป็นไปไม่ได้ที่จะคำนวณหาสองแบบที่ h (m) = h (m ')

ทั้งสองกรณีไม่เหมือนกัน ในกรณีแรกมีแฮชที่มีอยู่แล้วที่คุณกำลังพยายามหาการชนกัน ในกรณีที่สองคุณกำลังพยายามค้นหาข้อความใด ๆสองข้อความที่ชนกัน ภารกิจที่สองนั้นง่ายกว่ามากเนื่องจากวันเกิด "บุคคลที่ผิดธรรมดา"

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

อย่าใช้ MD5 หรือ SHA-1 ในการออกแบบใหม่ ฉันรวม cryptographers ส่วนใหญ่แล้วจะถือว่ามันแตก แหล่งที่มาหลักของความอ่อนแอในการออกแบบทั้งสองนี้คือคุณสมบัติที่สองซึ่งฉันได้กล่าวไว้ข้างต้นไม่ได้มีไว้สำหรับสิ่งปลูกสร้างเหล่านี้ หากผู้โจมตีสามารถสร้างข้อความสองข้อความคือ m และ m 'ซึ่งทั้งคู่แฮชเป็นค่าเดียวกันพวกเขาสามารถใช้ข้อความเหล่านี้กับคุณ SHA-1 และ MD5 ยังประสบกับการโจมตีของส่วนขยายข้อความซึ่งอาจทำให้แอปพลิเคชันของคุณอ่อนแอลงหากคุณไม่ระวัง

แฮชที่ทันสมัยกว่าเช่น Whirpool เป็นตัวเลือกที่ดีกว่า ไม่ได้รับผลกระทบจากการโจมตีของส่วนขยายข้อความและใช้คณิตศาสตร์แบบเดียวกับที่ AES ใช้เพื่อพิสูจน์ความปลอดภัยจากการโจมตีที่หลากหลาย

หวังว่าจะช่วย!


1
ฉันคิดว่าคำแนะนำเกี่ยวกับฟังก์ชันแฮชการเข้ารหัสลับเป็นคำแนะนำที่ไม่ดีจริงๆในกรณีนี้
สลาวา

@Slava: ทำไม คุณมีเหตุผลอะไรในการพูดว่า "ฟังก์ชันแฮชการเข้ารหัสลับเป็นคำแนะนำที่ไม่ดีจริงๆในกรณีนี้" ทำไมคำแนะนำที่ไม่ดี? อะไรคือข้อเสียที่ทำให้มันเป็นเช่นนั้น?
ให้ฉัน Tink เกี่ยวกับเรื่องนี้

2
@Mowzer เนื่องจากฟังก์ชั่นแฮชที่ใช้ในแผนที่แฮชควรจะรวดเร็วและมีน้ำหนักเบา (สมมติว่ามันยังมีแฮชที่ดี) แฮ็กเข้ารหัสลับได้ชัดเจนว่าสาวใช้จะมีราคาแพงเพื่อป้องกันการโจมตีด้วยกำลังดุร้าย
Slava

1

สิ่งที่คุณพูดในที่นี้คือคุณต้องการมีสิ่งที่ใช้มีความต้านทานการชน ลองใช้ SHA-2 หรือลองใช้บล็อกตัวเลข (ดี) ในฟังก์ชันการบีบอัดข้อมูลทางเดียว (ไม่เคยลองมาก่อน) เช่น AES ในโหมด Miyaguchi-Preenel ปัญหาที่เกิดขึ้นคือคุณต้อง:

1) มี IV ลองใช้ 256 บิตแรกของส่วนที่เป็นเศษส่วนของค่าคงที่ของ Khinchin หรืออะไรทำนองนั้น 2) มีรูปแบบการแพ็ด ง่าย. รถเข็นจาก hash เช่น MD5 หรือ SHA-3 (Keccak [ออกเสียง 'ket-chak']) ถ้าคุณไม่สนใจเรื่องความปลอดภัย (มีอีกไม่กี่คนที่พูดแบบนี้) ดูที่ FNV หรือ lookup2 โดย Bob Jenkins (ที่จริงฉันเป็นคนแรกที่แนะนำการค้นหา 2) ลองใช้ MurmurHash ได้อย่างรวดเร็ว (ตรวจสอบนี้: .16 cpb )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.