XOR हैश को संयोजित करने का डिफ़ॉल्ट तरीका क्यों है?


145

कहते हैं कि तुम दो हैश है H(A)और H(B)और आप उन्हें गठबंधन करने के लिए चाहते हैं। मैंने पढ़ा है कि दो हैश को संयोजित करने का एक अच्छा तरीका है XOR, जैसे XOR( H(A), H(B) )

सबसे अच्छा विवरण जो मैंने पाया है वह इन हैश फ़ंक्शन दिशानिर्देशों पर संक्षेप में छुआ गया है :

मोटे तौर पर यादृच्छिक वितरण * के साथ एक और संख्या में लगभग यादृच्छिक वितरण परिणामों के साथ दो नंबर XORing, लेकिन जो अब दो मूल्यों पर निर्भर करता है।
...
* गठबंधन करने के लिए दो संख्याओं में से प्रत्येक में, एक 0 आउटपुट है यदि दो बिट्स समान हैं, तो एक 1. अन्य शब्दों में, 50% संयोजन में, 1 एक आउटपुट होगा। इसलिए यदि दो इनपुट बिट्स में से प्रत्येक में 0 या 1 होने का लगभग 50-50 मौका है, तो इसलिए आउटपुट बिट भी होगा।

क्या आप इसके पीछे अंतर्ज्ञान और / या गणित की व्याख्या कर सकते हैं कि क्यों XOR हैश फ़ंक्शन (या OR और आदि) के संयोजन के लिए डिफ़ॉल्ट ऑपरेशन होना चाहिए?


20
मुझे लगता है कि आपने अभी किया है;)
मास

22
ध्यान दें कि XOR हैश को "संयोजित" करने का "अच्छा" तरीका नहीं हो सकता है, यह इस बात पर निर्भर करता है कि आप "संयोजन" में क्या चाहते हैं। XOR सराहनीय है: XOR (H (A), H (B)) XOR (H (B), H (A)) के बराबर है। इसका मतलब यह है कि XOR मूल्यों के एक क्रमबद्ध अनुक्रम का एक प्रकार का हैश बनाने के लिए एक उचित तरीका नहीं है, क्योंकि यह आदेश पर कब्जा नहीं करता है।
थॉमस पोर्निन

6
आदेश के साथ मुद्दा (ऊपर टिप्पणी) के साथ, समान मूल्यों के साथ समस्या है। XOR (H (1), H (1)) = 0 (किसी भी फ़ंक्शन H के लिए), XOR (H (2), H (2)) = 0 और इतने पर। किसी भी N: XOR (H (N), H (N)) = 0 के लिए। समान मूल्य वास्तविक ऐप्स में काफी बार होता है, इसका मतलब है कि XOR का परिणाम 0 होगा अक्सर इसे अच्छा हैश माना जाता है।
आंद्रेई गलाटिन

मूल्यों के क्रमबद्ध क्रम के लिए आप क्या उपयोग करते हैं? मान लीजिए कि मैं टाइमस्टैम्प या इंडेक्स का हैश बनाना चाहता हूं। (LSB LSB से कम महत्वपूर्ण)। क्षमा करें यदि यह धागा 1 वर्ष पुराना है।
एलेक्सिस

जवाबों:


120

समान रूप से यादृच्छिक (1-बिट) इनपुट मानते हुए, और फ़ंक्शन आउटपुट संभावना वितरण 75% 0और 25% है 1। इसके विपरीत, OR 25% 0और 75% है 1

XOR फ़ंक्शन 50% 0और 50% है 1, इसलिए यह समान संभावना वितरण के संयोजन के लिए अच्छा है।

इसे सत्य सारणी लिखकर देखा जा सकता है:

 a | b | a AND b
---+---+--------
 0 | 0 |    0
 0 | 1 |    0
 1 | 0 |    0
 1 | 1 |    1

 a | b | a OR b
---+---+--------
 0 | 0 |    0
 0 | 1 |    1
 1 | 0 |    1
 1 | 1 |    1

 a | b | a XOR b
---+---+--------
 0 | 0 |    0
 0 | 1 |    1
 1 | 0 |    1
 1 | 1 |    0

व्यायाम: दो 1-बिट इनपुट के कितने तार्किक कार्य हैं aऔर bयह एक समान आउटपुट वितरण है? XOR आपके प्रश्न में बताए गए उद्देश्य के लिए सबसे उपयुक्त क्यों है?


24
व्यायाम का उत्तर देना: 16 अलग-अलग एक्सएक्सएक्स बी ऑपरेशनों से (0, a & b, a > b, a, a < b, b, a % b, a | b, !a & !b, a == b, !b, a >= b, !a, a <= b, !a | !b, 1), निम्नलिखित में 0 और 1 के 50% -50% वितरण होते हैं, यह मानते हुए कि ए और बी में 0 और 1 एस के 50% -50% वितरण हैं: a, b, !a, !b, a % b, a == bअर्थात, विपरीत XOR (EQUIV) के रूप में अच्छी तरह से इस्तेमाल किया जा सकता था ...
मस्सा

7
ग्रेग, यह एक कमाल का जवाब है। आपके मूल उत्तर को देखने के बाद प्रकाश बल्ब मेरे लिए चला गया और अपनी सत्य सारणी लिखी। मैंने @ मस्सा के जवाब पर विचार किया कि वितरण को बनाए रखने के लिए 6 उपयुक्त संचालन कैसे हैं। और जबकि a, b, !a, !bउनके संबंधित इनपुट के समान वितरण होगा, आप अन्य इनपुट की एन्ट्रापी खो देते हैं। यही है, XOR हैश के संयोजन के उद्देश्य के लिए सबसे उपयुक्त है क्योंकि हम ए और बी दोनों से एन्ट्रापी पर कब्जा करना चाहते हैं।
नैट मरे

1
यहां एक पेपर है जो बताता है कि हैश को सुरक्षित रूप से संयोजित करना जहां प्रत्येक फ़ंक्शन को केवल एक बार कहा जाता है, प्रत्येक हैश मान में बिट्स की संख्या की तुलना में कम बिट्स आउटपुट के बिना संभव नहीं है। यह सुझाव देता है कि यह उत्तर सही नहीं है।
तमसे सजेलेई

3
@ मासा मैंने कभी XOR के लिए% का उपयोग नहीं देखा है या नहीं के बराबर है।
ब्यूज

7
जैसा कि यक्क बताते हैं , एक्सओआर खतरनाक हो सकता है क्योंकि यह समान मूल्यों के लिए शून्य पैदा करता है। इसका मतलब है (a,a)और (b,b)दोनों शून्य का उत्पादन करते हैं, जो कई (अधिकांश?) मामलों में हैश-आधारित डेटा संरचनाओं में टकराव की संभावना को बहुत बढ़ाता है।
ड्रू नोक

170

xorहैशिंग के लिए उपयोग करने के लिए एक खतरनाक डिफ़ॉल्ट फ़ंक्शन है। यह बेहतर है andऔर or, लेकिन यह बहुत कुछ नहीं कहता है।

xorसममित है, इसलिए तत्वों का क्रम खो गया है। तो "bad"हैश के रूप में ही गठबंधन होगा "dab"

xor नक्शे शून्य के समरूप मानों को जोड़ते हैं, और आपको "सामान्य" मानों को शून्य करने से बचना चाहिए:

तो (a,a)0 पर मैप हो जाता है, और (b,b)0. के लिए मैप भी हो जाता है। क्योंकि ऐसी जोड़ियां लगभग हमेशा से ज्यादा सामान्य होती हैं, जैसे कि यादृच्छिकता का अर्थ हो सकता है, आप शून्य से कई टकरावों की तुलना में दूर होना चाहिए।

इन दो समस्याओं के साथ, xorएक हैश कॉम्बीनेटर होता है जो सतह पर आधा सभ्य दिखता है, लेकिन आगे के निरीक्षण के बाद नहीं।

आधुनिक हार्डवेयर पर, आमतौर पर उपवास के रूप में जोड़ते हैं xor(यह संभवतः इस बंद को खींचने के लिए अधिक शक्ति का उपयोग करता है, संयुक्त रूप से)। सच्चाई की तालिका को जोड़ना xorसवाल में बिट पर समान है , लेकिन जब दोनों मान 1 होते हैं तो यह अगले बिट को भी भेजता है। इसका मतलब है कि यह कम जानकारी मिटाता है।

तो उस hash(a) + hash(b)से बेहतर hash(a) xor hash(b)है अगर a==b, परिणाम hash(a)<<10 के बजाय है।

यह सममित रहता है; इसलिए "bad"और "dab"एक ही परिणाम प्राप्त करना एक समस्या है। हम मामूली लागत के लिए इस समरूपता को तोड़ सकते हैं:

hash(a)<<1 + hash(a) + hash(b)

उर्फ hash(a)*3 + hash(b)। ( hash(a)यदि आप शिफ्ट समाधान का उपयोग करते हैं तो एक बार गणना करना और भंडारण की सलाह दी जाती है)। किसी भी विषम स्थिरांक के बजाय अपने आप में 3एक " k-bit" अहस्ताक्षरित पूर्णांक को मैप करेगा, क्योंकि अहस्ताक्षरित पूर्णांकों पर मानचित्र 2^kकुछ के लिए गणित मोडुलो है k, और किसी भी विषम स्थिरांक के लिए अपेक्षाकृत प्रमुख है 2^k

एक भी कट्टर संस्करण के लिए, हम जांच कर सकते हैं boost::hash_combine, जो प्रभावी रूप से है:

size_t hash_combine( size_t lhs, size_t rhs ) {
  lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
  return lhs;
}

यहाँ हम seedएक स्थिरांक के साथ कुछ बदलाव किए गए संस्करणों को जोड़ते हैं (जो मूल रूप से यादृच्छिक 0s और 1s है - विशेष रूप से यह कुछ अनुपात और एक xor के साथ सुनहरे अनुपात का एक 32 बिट निश्चित अंश के रूप में व्युत्क्रम है)। यह समरूपता को तोड़ता है, और कुछ "शोर" का परिचय देता है यदि आने वाले हैशेड मान खराब होते हैं (यानी, प्रत्येक घटक हैश की 0 से कल्पना करें - ऊपर यह अच्छी तरह से संभालता है, प्रत्येक संयोजन के बाद 1और 0एस का एक धब्बा पैदा करता है । मेरा भोलापन 3*hash(a)+hash(b)बस एक 0में आउटपुट करता है । उस मामले में)।

(उन लोगों के लिए जो C / C ++ से परिचित नहीं हैं, एक size_tअहस्ताक्षरित पूर्णांक मान है जो स्मृति में किसी भी वस्तु के आकार का वर्णन करने के लिए पर्याप्त है। 64 बिट सिस्टम पर, यह आमतौर पर 64 बिट अहस्ताक्षरित पूर्णांक है। 32 बिट सिस्टम पर। , एक 32 बिट अहस्ताक्षरित पूर्णांक।)


अच्छा जवाब याक। क्या यह एल्गोरिथ्म 32 बिट और 64 बिट सिस्टम पर समान रूप से अच्छी तरह से काम करता है? धन्यवाद।
डेव

1
@ अधिक बिट्स जोड़ने के लिए 0x9e3779b9
यक्क - एडम नेवरामोंट

10
ठीक है, पूरा होने के लिए ... यहाँ पूर्ण परिशुद्धता 64 बिट स्थिरांक है (लंबे डबल्स के साथ गणना की गई है, और अहस्ताक्षरित लंबे समय तक): 0x9e3779b97f4a7c16। दिलचस्प है कि यह अभी भी है। गोल्डन रेशो के बजाय पीआई का उपयोग करके उसी गणना को फिर से करना: 0x517cc1b727220a95 जो कि विषम है, यहां तक ​​कि इसके बजाय, इस प्रकार संभवतः "स्थिर" अन्य स्थिरांक से अधिक है। मैंने इस्तेमाल किया: std :: cout << std :: hex << (अहस्ताक्षरित लंबा लंबा) ((1.0L / 3.14159265358979383826433832795028288419716939937510L) * (powl (2.0L, 64.0L)) << std :: endl; cout.preaches (न्यूमेरिक_लिमिट्स <लॉन्ग डबल> :: max_digits10) के साथ; धन्यवाद फिर से यक।
डेव

2
@ इन मामलों के लिए उलटा सुनहरा अनुपात नियम है जो आपके द्वारा की जा रही गणना के बराबर या उससे बड़ी पहली विषम संख्या है। तो बस 1 जोड़ें। यह एक महत्वपूर्ण संख्या है क्योंकि N का अनुपात * अनुपात, मॉड अधिकतम आकार (2 ^ 64 यहाँ) अनुक्रम में अगले मूल्य को उस अनुपात में बिल्कुल सबसे बड़े 'गैप' के मध्य में रखता है। संख्या। अधिक जानकारी के लिए "फाइबोनैचि हैशिंग" के लिए वेब पर खोजें।
स्कॉट केरी

1
@Dave सही संख्या 0.9E3779B97F4A7C15F39 ... देखें होगा लिंक । आप गोल-से-सम नियम (जो एकाउंटेंट के लिए अच्छा है) से पीड़ित हो सकते हैं, या बस, यदि आप शाब्दिक sqrt (5) निरंतर के साथ शुरू करते हैं, जब आप 1 घटाते हैं, तो आप उच्च क्रम बिट को हटा देते हैं, थोड़ा खो गया होगा।
16

29

अपने काम बिट मिश्रण गुण के बावजूद, XOR है नहीं एक अच्छा तरीका है अपने commutativity की वजह से हैश गठबंधन करने के लिए। विचार करें कि यदि आप 10-ट्यूपल्स के हैश टेबल में {1, 2,…, 10} के क्रमचयों को संग्रहीत करते हैं तो क्या होगा।

एक बेहतर विकल्प है m * H(A) + H(B), जहां मी एक बड़ी विषम संख्या है।

क्रेडिट: उपरोक्त कॉम्बिनेटर बॉब जेनकिंस से एक टिप था।


2
कभी-कभी कम्यूटेटिविटी एक अच्छी बात होती है, लेकिन फिर भी ज़ार एक घटिया विकल्प होता है , क्योंकि मिलान करने वाले सभी जोड़े शून्य तक पहुंच जाएंगे। एक अंकगणितीय योग बेहतर है; मिलान वाली वस्तुओं की एक जोड़ी का हैश 32 के बजाय उपयोगी डेटा के केवल 31 बिट्स को बनाए रखेगा, लेकिन यह शून्य बनाए रखने से बहुत बेहतर है। एक अन्य विकल्प अंकगणितीय योग की गणना करना हो सकता है longऔर फिर निचले हिस्से के साथ ऊपरी हिस्से को पीछे करना होगा।
सुपरकार

1
m = 3वास्तव में एक अच्छा विकल्प है और कई प्रणालियों पर बहुत तेज है। ध्यान दें कि किसी भी विषम mपूर्णांक गुणन के लिए modulo है 2^32या 2^64इसलिए यह उलटा है इसलिए आप किसी भी बिट को नहीं खो रहे हैं।
स्टेफानकारपिंस्की

जब आप MaxInt से आगे जाते हैं तो क्या होता है?
विघटनकारी

2
किसी भी विषम संख्या के बजाय एक प्रधानमंत्री को चुनना चाहिए
टर्मोक्स

2
@Infinum जब हैश का संयोजन आवश्यक नहीं है।
मार्सेलो कैंटोस

17

Xor हैश को संयोजित करने का "डिफ़ॉल्ट" तरीका हो सकता है लेकिन ग्रेग हेगिल के उत्तर से यह भी पता चलता है कि इसके नुकसान क्यों हैं: दो समान हैश मानों का xor शून्य है। वास्तविक जीवन में, समान हैश एक से अधिक सामान्य हो सकते हैं जो किसी ने उम्मीद की हो। तब आप पा सकते हैं कि इन (इतने अचूक) कोने के मामलों में, परिणामस्वरूप संयुक्त हैश हमेशा एक ही (शून्य) नहीं होते हैं। हैश टकराव आपकी अपेक्षा से बहुत अधिक, बहुत अधिक बार होगा।

एक आकस्मिक उदाहरण में, आप अपने द्वारा प्रबंधित विभिन्न वेबसाइटों के उपयोगकर्ताओं के हैशेड पासवर्ड का संयोजन कर सकते हैं। दुर्भाग्य से, बड़ी संख्या में उपयोगकर्ता अपने पासवर्ड का पुन: उपयोग करते हैं, और परिणामी हैश का एक आश्चर्यजनक अनुपात शून्य है!


मुझे उम्मीद है कि आकस्मिक उदाहरण कभी नहीं होगा, पासवर्ड को नमकीन होना चाहिए।
user60561

8

ऐसा कुछ है जो मैं इस पृष्ठ को खोजने वाले अन्य लोगों के लिए स्पष्ट रूप से इंगित करना चाहता हूं। BlueRaja की तरह AND और OR आउटपुट को प्रतिबंधित करता है - डैनी पफ्लुघो इंगित करने की कोशिश कर रहा है, लेकिन बेहतर परिभाषित किया जा सकता है:

पहले मैं दो सरल कार्यों को परिभाषित करना चाहता हूं जिन्हें मैं यह समझाने के लिए उपयोग करूंगा: न्यूनतम () और मैक्स ()।

मिन (ए, बी) ए और बी के बीच छोटे मान को लौटाएगा, उदाहरण के लिए: मिन (1, 5) रिटर्न 1।

मैक्स (ए, बी) ए और बी के बीच बड़ा मान लौटाएगा, उदाहरण के लिए: मैक्स (1, 5) रिटर्न 5।

यदि आपको दिया जाता है: C = A AND B

तब आप पा सकते हैं कि C <= Min(A, B)हम यह जानते हैं क्योंकि आप 1s बनाने के लिए A या B के 0 बिट्स के साथ कुछ भी नहीं कर सकते हैं। तो प्रत्येक शून्य बिट शून्य बिट रहता है और प्रत्येक बिट में एक शून्य बिट (और इस प्रकार एक छोटा मान) बनने का मौका होता है।

साथ में: C = A OR B

विपरीत सच है: C >= Max(A, B)इसके साथ, हम कोरोलरी को AND फ़ंक्शन में देखते हैं। कोई भी बिट जो पहले से ही एक शून्य में होने का आदेश नहीं दिया जा सकता है, इसलिए यह एक रहता है, लेकिन हर शून्य बिट में एक बनने का मौका है, और इस प्रकार एक बड़ी संख्या है।

इसका तात्पर्य है कि इनपुट की स्थिति आउटपुट पर प्रतिबंध लागू करती है। यदि आप और 90 के साथ कुछ भी करते हैं, तो आप जानते हैं कि आउटपुट 90 या उससे कम के बराबर होगा, भले ही अन्य मूल्य क्या हो।

XOR के लिए, इनपुट्स के आधार पर कोई निहित प्रतिबंध नहीं है। ऐसे विशेष मामले हैं जहां आप पा सकते हैं कि यदि आप 255 से बाइट करते हैं तो आपको उलटा मिलता है, लेकिन किसी भी संभावित बाइट का उत्पादन इससे किया जा सकता है। हर बिट के पास दूसरे ऑपरेंड में उसी बिट के आधार पर स्थिति बदलने का मौका है।


6
एक कह सकते हैं कि ORहै बिटवाइज़ अधिकतम , और ANDहै बिटवाइज़ मिनट
पाओलो एबरमन

बहुत अच्छी तरह से पॉलो एबरमन ने कहा। यहाँ आपको Crypto.SE देखकर अच्छा लगा!
कोरी ओगबर्न

मैंने एक फ़िल्टर बनाया , जिसमें मुझे सब कुछ शामिल है क्रिप्टोग्राफी , पुराने प्रश्नों में भी परिवर्तन। इस तरह मुझे आपका जवाब यहाँ मिल गया।
पाओलो एबरमन

3

यदि आप XORएक पक्षपाती इनपुट के साथ एक यादृच्छिक इनपुट, आउटपुट यादृच्छिक है। उसी के लिए सच नहीं है ANDया OR। उदाहरण:

00101001 XOR 00000000 = 00101001
00101001 और 00000000 = 00000000
00101001 या 11111111 = 11111111

जैसा कि @Gew Hewgill उल्लेख करता है, भले ही दोनों इनपुट यादृच्छिक हो, का उपयोग कर ANDया ORपक्षपाती आउटपुट में परिणाम देगा।

जिस कारण से हम XORकुछ अधिक जटिल का उपयोग करते हैं, वह है, ठीक है, इसकी कोई आवश्यकता नहीं है: XORपूरी तरह से काम करता है, और यह आश्चर्यजनक रूप से बेवकूफ-तेज़ है।


1

बाएं 2 कॉलम को कवर करें और यह पता लगाने की कोशिश करें कि क्या इनपुट सिर्फ आउटपुट का उपयोग कर रहे हैं।

 a | b | a AND b
---+---+--------
 0 | 0 |    0
 0 | 1 |    0
 1 | 0 |    0
 1 | 1 |    1

जब आपने 1-बिट देखा, तो आपको काम करना चाहिए था कि दोनों इनपुट 1 थे।

अब XOR के लिए भी यही करें

 a | b | a XOR b
---+---+--------
 0 | 0 |    0
 0 | 1 |    1
 1 | 0 |    1
 1 | 1 |    0

XOR इनपुट के बारे में कुछ भी नहीं देता है।


0

के विभिन्न संस्करणों के लिए स्रोत कोड hashCode()में java.util.Arrays ठोस, सामान्य उपयोग हैशिंग एल्गोरिदम के लिए एक महान संदर्भ है। उन्हें आसानी से समझा और अन्य प्रोग्रामिंग भाषाओं में अनुवाद किया जाता है।

मोटे तौर पर, अधिकांश बहु-विशेषता hashCode()कार्यान्वयन इस पैटर्न का अनुसरण करते हैं:

public static int hashCode(Object a[]) {
    if (a == null)
        return 0;

    int result = 1;

    for (Object element : a)
        result = 31 * result + (element == null ? 0 : element.hashCode());

    return result;
}

आप जादू के बारे में अधिक जानकारी के लिए अन्य StackOverflow Q & As की खोज कर सकते हैं 31, और जावा कोड इसका बार-बार उपयोग क्यों करता है। यह अपूर्ण है, लेकिन इसमें बहुत अच्छी सामान्य प्रदर्शन विशेषताएं हैं।


2
जावा का डिफ़ॉल्ट "31 से गुणा और जोड़ें / संचित करें" हैश को टक्करों (जैसे stringकि string + "AA"IIRC के साथ कोई भी टकराता है ) के साथ लोड किया जाता है और वे बहुत पहले चाहते थे कि वे उस एल्गोरिथ्म में युक्ति में बेक न हुए हों। उस ने कहा, अधिक बिट सेट के साथ एक बड़ी विषम संख्या का उपयोग करना, और एक पारियों या घुमाव को जोड़ना उस समस्या को ठीक करता है। मुरमुरैश 3 का 'मिक्स' यही करता है।
स्कॉट केरी

0

XOR कभी-कभी OR और AND जैसे कुछ इनपुट्स को नजरअंदाज नहीं करता है ।

यदि आप उदाहरण के लिए AND (X, Y) लेते हैं , और इनपुट X को गलत के साथ फीड करते हैं, तो इनपुट Y कोई मायने नहीं रखता ... और एक संभवतया इनपुट को हैश को मिलाते समय मायने रखता है।

यदि आप XOR (X, Y) लेते हैं , तो दोनों चीजें हमेशा भिन्न होती हैं। ऐसे X का कोई मान नहीं होगा जहां Y कोई मायने नहीं रखता। यदि या तो X या Y को बदल दिया जाता है तो आउटपुट उसे प्रतिबिंबित करेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.