2011-08-30 17 views
6

byte की सरणी के लिए सबसे अच्छी हैश विधि क्या है?बाइट्स की सरणी के लिए उपयुक्त हैश कोड विधियां?

सरणी धारावाहिक वर्ग वस्तुओं वाली हैं जिनमें टीसीपी/आईपी पर अनुप्रयोगों के बीच जेपीईजी छवि होती है।

सरणी का आकार लगभग 200k है।

+0

सुरक्षित या असुरक्षित कोड? – xanatos

+0

सुरक्षित, बस 'बाइट [] 'सर –

उत्तर

9

अंतर्निर्मित हैशिंग कार्यों में से कोई भी करना चाहिए; आप कितना टकराव के बारे में परवाह के आधार पर इन (सबसे टकराव से कम से कम करने के लिए) अपने विकल्प हैं:

  • MD5
  • SHA1
  • SHA256
  • SHA384
  • SHA512

वे के रूप में उपयोग करने के लिए सरल हैं:

var hash = SHA1.Create().ComputeHash(data); 

बोनस मार्क्स: यदि आपको सुरक्षा की परवाह नहीं है (जो मुझे नहीं लगता कि आपको यह दिया गया है कि आपको छवियों के लिए हैंश मिल रही हैं) तो आप मर्मूर हैश को देखना चाहते हैं, जो सामग्री हैशिंग के लिए डिज़ाइन किया गया है और सुरक्षित हैशिंग (और इस प्रकार बहुत तेज़ है)। हालांकि, यह ढांचे में नहीं है, इसलिए आपको एक कार्यान्वयन मिलना होगा (और आपको शायद मुर्मूर 3 के लिए जाना चाहिए)।

संपादित करें: आप देख रहे हैं एक बाइट [] सरणी यह ​​पूरी तरह आप पर निर्भर है के लिए एक हैशकोड के लिए, यह आमतौर पर बिट (अभाज्य संख्या से) स्थानांतरण और XORing के होते हैं। जैसे

public class ByteArrayEqualityComparer : IEqualityComparer<byte[]> 
{ 
    public static readonly ByteArrayEqualityComparer Default = new ByteArrayEqualityComparer(); 
    private ByteArrayEqualityComparer() { } 

    public bool Equals(byte[] x, byte[] y) 
    { 
     if (x == null && y == null) 
      return true; 
     if (x == null || y == null) 
      return false; 
     if (x.Length != y.Length) 
      return false; 
     for (var i = 0; i < x.Length; i++) 
      if (x[i] != y[i]) 
       return false; 
     return true; 
    } 

    public int GetHashCode(byte[] obj) 
    { 
     if (obj == null || obj.Length == 0) 
      return 0; 
     var hashCode = 0; 
     for (var i = 0; i < obj.Length; i++) 
      // Rotate by 3 bits and XOR the new value. 
      hashCode = (hashCode << 3) | (hashCode >> (29))^obj[i]; 
     return hashCode; 
    } 
} 
// ... 
var hc = ByteArrayEqualityComparer.Default.GetHashCode(data); 

संपादित करें: आप मान्य करने के लिए है कि मूल्य आप CRC32 का उपयोग करना चाहिए नहीं बदला है चाहते हैं।

+0

उत्तर के लिए धन्यवाद, मुझे केवल 'बाइट [] 'सरणी सामग्री तुलना की आवश्यकता है, इसमें लिखित हैंश की आवश्यकता नहीं है। मुझे यह सुनिश्चित करने की ज़रूरत है कि भेजा गया डेटा वही रहता है क्योंकि इसे दूसरे छोर पर प्राप्त किया जाता है –

+0

@ चेसनोकोव तो आपने पहली जगह क्यों नहीं पूछा? –

+0

मेरा मतलब हैश मूल्य से तुलना, जैसा कि सवाल में है, डेटा हैश के साथ इंटरनेट पर भेजा जाता है। दूसरे छोर पर हैश को फिर से तैयार किया गया है और यह सुनिश्चित करने के लिए तुलना की गई है कि हस्तांतरण के दौरान डेटा पर कोई संशोधन नहीं किया गया था –

2

क्रिप्टो हैशिंग सामग्री में से कोई भी काम करना चाहिए। गति के बारे में निश्चित नहीं है। शायद एमडी 5?

+0

बाइट [] सरणी के लिए .NET में कोई कस्टम तरीका है, केवल त्वरित तुलना में, मुझे एन्क्रिप्शन की आवश्यकता नहीं है अभी तक –

+0

@ चेसनोकोव जो एक अलग प्रश्न की तरह लगता है; जैसे: http://stackoverflow.com/questions/43289/comparing-two-byte-arrays-in-net –

+0

ओह, नहीं। मुझे 'बाइट []' सरणी के लिए 32 बिट मान प्राप्त करने के लिए एक तेज विधि की आवश्यकता है। सीरियलाइज्ड ऑब्जेक्ट को अपने हैश के साथ अन्य मशीन पर भेजा जाता है जहां हैश को फिर से दबाया जाता है और –

2

Compiler Generated GetHashCode()

public static int GetHashCode(byte[] array) { 
    unchecked { 
     int i = 0; 
     int hash = 17; 
     int rounded = array.Length & ~3; 

     hash = 31 * hash + array.Length; 

     for (; i < rounded; i += 4) { 
      hash = 31 * hash + BitConverter.ToInt32(array, i); 
     } 

     if (i < array.Length) { 
      int val = array[i]; 
      i++; 

      if (i < array.Length) { 
       val |= array[i] << 8; 
       i++; 

       if (i < array.Length) { 
        val |= array[i] << 16; 
       } 
      } 

      hash = 31 * hash + val; 
     } 

     return hash; 
    } 
} 

आह के आधार पर ... और जो सामान्य प्रभावी हैश तकनीक है जहाँ आप एक साथ शुरू करने पर आधारित है कैसे GetHashCode, ओवरराइड करने के लिए पर सी # Murmurhash http://landman-code.blogspot.com/2009/02/c-superfasthash-and-murmurhash2.html

+0

अच्छा जवाब, लेकिन यह मुर्मूर 2 है जिसमें दोहराने वाले डेटा के साथ समस्याएं हैं (अगर वहां होता है तो यह अक्सर गिरता है)। मैं मुर्मूर 3 के किसी भी सी # बंदरगाहों के बारे में नहीं जानता। –

+0

मुर्मूर 3 कार्यान्वयन http://blog.teamleadnet.com/2012/08/murmurhash3-ultra-fast-hash-algorithm.html – Omar

4

Jon Skeet has a good answer के लिए एक लिंक प्राइम नंबर, इसे ओवरफ्लो के लिए अनुमति देने वाले अन्य प्राइम नंबर से गुणा घटकों के हैश कोड में जोड़ें।

अपने मामले के लिए, आप क्या करेंगे: जॉन के जवाब में

static int GetByteArrayHashCode(byte[] array) 
{ 
    unchecked 
    { 
     int hash = 17; 

     // Cycle through each element in the array. 
     foreach (var value in array) 
     { 
      // Update the hash. 
      hash = hash * 23 + value.GetHashCode();    
     } 

     return hash; 
    } 
} 

नोट वह क्यों इस अलग-अलग तत्वों के हैश (और सी # में अनाम प्रकार XORing वर्तमान में XOR नहीं है की तुलना में बेहतर है में चला जाता है व्यक्तिगत तत्वों के हैंश, लेकिन उपरोक्त के समान कुछ उपयोग करें)।

यह System.Security.Cryptography namespace (क्योंकि आप छोटे हैंश से निपट रहे हैं) से हैंश एल्गोरिदम से तेज़ होंगे, नकारात्मकता यह है कि आपके पास अधिक टकराव हो सकते हैं।

आपको अपने डेटा के खिलाफ परीक्षण करना होगा और यह निर्धारित करना होगा कि टकराव के मामले में आपको कितनी बार टक्कर मिल रही है।

+0

'foreach' 'के लिए 'धीमा' है? इसके अलावा, 'बाइट' पर 'GetHashCode' को कॉल करने की आवश्यकता नहीं है क्योंकि यह केवल' int' पर अपना मान डाला जाता है। –

+0

@DrewNoakes पूरी तरह से सुनिश्चित करें कि कंपाइलर 'for' के लिए सरणी पर' foreach' बदलता है। हालांकि यह एक कार्यान्वयन विस्तार है, और आम तौर पर आपको परीक्षण करना चाहिए यदि आप देखते हैं कि यह एक बाधा है। इसके अलावा, बाइट के लिए 'GetHashCode' के वापसी मूल्य के साथ ही। – casperOne

संबंधित मुद्दे