2012-09-28 9 views
7

पृष्ठभूमि (इस खंड आप छोड़ सकते हैं)SHA1Managed.ComputeHash कभी कभी अलग सर्वर

मैं डेटा (लगभग 3 एमबी) की एक बड़ी राशि है कई सौ मशीनों पर अद्यतित रखा जाना चाहिए पर अलग-अलग। कुछ मशीनें सी # और कुछ रन जावा चलाती हैं। डेटा किसी भी समय बदल सकता है और कुछ मिनटों के भीतर ग्राहकों को प्रचारित करने की आवश्यकता है। डेटा 4 लोड संतुलित सर्वर से जेसन प्रारूप में वितरित किया जाता है। ये 4 सर्वर एमएससी 3 और सी # 4.0 के साथ एएसपी.NET 4.0 चला रहे हैं।

4 सर्वरों पर चलने वाले कोड में हैशिंग एल्गोरिदम है जो जेसन प्रतिक्रिया को रोकता है और फिर हैश को स्ट्रिंग में परिवर्तित करता है। यह हैश ग्राहक को दिया गया है। फिर, हर कुछ मिनट, ग्राहक हैश के साथ सर्वर को पिंग करते हैं और यदि हैश पुराना है तो नई जेसन ऑब्जेक्ट वापस आती है। यदि हैश अभी भी चालू है तो एक खाली निकाय के साथ 304 लौटा दिया जाता है।

कभी-कभी 4 बक्से द्वारा उत्पन्न हैंश बक्से में असंगत होते हैं, जिसका अर्थ है कि ग्राहक लगातार डेटा डाउनलोड कर रहे हैं (प्रत्येक अनुरोध एक अलग सर्वर को मार सकता है)।

कोड Snipet

यहाँ कोड है कि हैश उत्पन्न करने के लिए प्रयोग किया जाता है।

internal static HashAlgorithm Hasher { get; set; } 
... 
Hasher = new SHA1Managed(); 
... 
Convert.ToBase64String(Hasher.ComputeHash(Encoding.ASCII.GetBytes(jsonString))); 

कोशिश करते हैं और समस्या मैं इस तरह इसे बाहर विभाजित डिबग करने के लिए:

Prehash = PreHashBuilder.ToString(); 
ASCIIBytes = Encoding.ASCII.GetBytes(Prehash); 
HashedBytes = Hasher.ComputeHash(ASCIIBytes); 
Hash = Convert.ToBase64String(HashedBytes); 

मैं तो एक मार्ग जो ऊपर मूल्यों बाहर थूक जोड़ा और परे मतभेद तुलना करने के लिए की तुलना में इस्तेमाल किया।

बाइट सरणियों का उपयोग करके BeyondCompare उपयोग के लिए एक स्ट्रिंग स्वरूप में परिवर्तित कर रहे हैं:

private static string GetString(byte[] bytes) 
{ 
    StringBuilder sb = new StringBuilder(); 
    foreach (byte b in bytes) 
    { 
     sb.Append(b); 
    } 
    return sb.ToString(); 
} 

आप देख सकते हैं बाइट सरणी बाइट्स की एक दृश्य के रूप में litterally प्रदर्शित होता है। यह 'रूपांतरित' नहीं है।

समस्या

मुझे पता चला कि Prehash और ASCIIBytes मान एक ही थे, लेकिन HashedBytes मान भिन्न थे - जिसका मतलब था कि हैश भी अलग था।

मैंने आईओएस वेबसाइट्स को 4 सर्वर बॉक्स पर कई बार पुनरारंभ किया, और जब उनके पास अलग-अलग हैंश थे, तो बायोन्डकंपारे में मूल्यों की तुलना में। everycase में यह "HashedBytes" मूल्य है कि विभिन्न() SHA1Managed.ComputeHash (के परिणाम ...) था

प्रश्न

क्या मैं गलत कर रहा हूँ? ComputeHash फ़ंक्शन में इनपुट समान है। SHA1 प्रबंधित मशीन निर्भर है? यह तब से नहीं बना है क्योंकि आधे समय में 4 मशीनों का एक ही हैश होता है।

मैंने स्टैक ओवर फ्लो और बिंग की खोज की है लेकिन इस समस्या के साथ किसी और को खोजने में असमर्थ रहे हैं। सबसे नज़दीकी चीज जो मुझे मिल सकती थी वह लोगों को उनके एन्कोडिंग के साथ समस्या थी, लेकिन मुझे लगता है कि मैंने साबित कर दिया है कि एन्कोडिंग कोई मुद्दा नहीं है।

हैश: o1ZxBaVuU6OhE6De96wJXUvmz3M =
HashedBytes

आउटपुट

मैं यहाँ क्योंकि कितना समय लगता है, लेकिन यहाँ की सब कुछ डंप करने के लिए नहीं उम्मीद कर रही थी डंप मैं की तुलना कर रहा हूँ की एक snipet है: 163861135165110831631611916022224717299375230207115
ASCIIBytes: 115116971031014699111109477911410010111483101114118105991014711510111411810599101461151189959115105103110117112951151011141181059910111410110210111410111099101115959897991071011101001111141001011141151011141181059910195 1185095117114108611041161161125847471051159897991071011101004610910211598101115116971031014699111109477911410010111483101114118105991014711510111411810599101461151189947118505911510510311011711295115101114118105991011141011021011141011109910111595989799107101110100112971211091011101161151161111141011151011141 .... Prehash: ...

जब मैं अलग सर्वर पर दो पृष्ठों की तुलना ASCII बाइट्स समान हैं लेकिन HashedBytes नहीं हैं। बाइट्स के लिए उपयोग की जाने वाली डंप विधि में कोई रूपांतरण नहीं होता है, यह बस अनुक्रम में प्रत्येक बाइट को डंप करता है। मैं बाइट्स को '' 'से सीमित कर सकता था। मुझे लगता है।

ऊपर का पालन मैं b.ToString (CultureInfo.InvariantCulture) परिवर्तन किया है और HashAlgorithm एक स्थानीय चर के बजाय एक स्थिर संपत्ति बना दिया है। मैं कोड को सर्वर पर तैनात करने की प्रतीक्षा कर रहा हूं।

+4

एक स्ट्रिंग को डंप करने और इसे जांचने के बजाय (जो आपका टूल कुछ अंतरों को अनदेखा कर सकता है) बाइट्स को डंप करें और देखें कि वे तुलना कैसे करते हैं। – CrazyCasta

+0

क्या 'हैशडबाइट्स' बिल्कुल वही हैं? –

+0

@ माइक नहीं, वह कह रहा है कि वे अलग हैं। – CrazyCasta

उत्तर

9

मैं इस मुद्दे नकल करने की कोशिश कर रहा है, लेकिन ऐसा करने में असमर्थ किया गया है एक बार मैं SHA1Managed संपत्ति एक स्थानीय चर के बजाय वैश्विक स्थिर बना दिया।

समस्या मल्टी-थ्रेडिंग के साथ किया गया था। मेरा कोड थ्रेड सुरक्षित था जो SHA1 प्रबंधित वर्ग को छोड़कर मैंने स्थिर चिह्नित किया था। मैं मान लिया है कि SHA1Managed.ComputeHash धागा सुरक्षित नीचे होगा, लेकिन जाहिरा तौर पर यह आंतरिक स्थिर चिह्नित करता है, तो नहीं कर रहा है।

दोहराने के लिए, SHA1Managed.ComputeHash सुरक्षित थ्रेड नहीं है, तो आंतरिक स्थिर चिह्नित।

MSDN राज्यों:

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe. 

मैं क्यों आंतरिक स्थिर सार्वजनिक स्थिर तुलना में अलग तरह से व्यवहार करता है पता नहीं है।

मैं उत्तर के रूप में @pst को चिह्नित करता हूं और समस्या को स्पष्ट करने के लिए एक टिप्पणी जोड़ता हूं, लेकिन @pst ने एक टिप्पणी की है इसलिए मैं इसे उत्तर के रूप में चिह्नित नहीं कर सकता।

आपके सभी इनपुट के लिए धन्यवाद।

+5

'SHA1Managed.ComputeHash' एक उदाहरण विधि है, एक स्थिर विधि नहीं है, इसलिए आप उस विधि को सुरक्षित रूप से उसी 'SHA1 प्रबंधित' उदाहरण पर कॉल नहीं कर सकते एक साथ कई धागे से। इससे कोई फर्क नहीं पड़ता कि 'हैशर' सार्वजनिक या आंतरिक है या नहीं। –

+0

इस सटीक मुद्दे ने मुझे भी पकड़ा, पोस्टिंग के लिए धन्यवाद। – fabspro

+0

इसे हल करने के लिए, मैंने कोड के चारों ओर एक लॉक (sha1obj) {} जोड़ा। यह देखने के लिए परीक्षण नहीं किए हैं कि लॉकिंग कई उदाहरण बनाने से धीमी है या नहीं, लेकिन यह मेरे उपयोग-मामले के लिए कोई मुद्दा नहीं है। – fabspro

0

आपकी गेटस्ट्रिंग विधि संभावित रूप से विभिन्न संस्कृतियों की मशीनों पर विभिन्न परिणामों का उत्पादन कर सकती है, क्योंकि स्ट्रिंगबिल्डर। ऐपेंड (बाइट) बाइट कॉल करता है। ToString (CultureInfo.CurrentCulture)।

private static string GetString(byte[] bytes) 
{ 
    StringBuilder sb = new StringBuilder(); 
    foreach (byte b in bytes) 
    { 
     sb.Append(b.ToString(CultureInfo.InvariantCulture)); 
    } 
    return sb.ToString(); 
} 

लेकिन एक विधि का उपयोग करना जो बाइट मानों के दशमलव स्ट्रिंग प्रस्तुतियों का उपयोग नहीं करता है बेहतर होगा।

0

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

using System.Runtime.Remoting.Metadata.W3cXsd2001; 

public byte[] StringToBytes(string value) 
{ 
    SoapHexBinary soapHexBinary = SoapHexBinary.Parse(value); 
    return soapHexBinary.Value; 
} 

public string BytesToString(byte[] value) 
{ 
    SoapHexBinary soapHexBinary = new SoapHexBinary(value); 
    return soapHexBinary.ToString(); 
} 

इसके अलावा, मुझे लगता है कि आप जाँच लें कि JSON विभिन्न सूक्ष्मता नहीं है, कि के रूप में एक पूरी तरह से अलग हैश बनाना होगा की सिफारिश करेंगे। उदाहरण के लिए कुछ संस्कृतियों संख्या "एक हजार छह सौ दशमलव सात" 1,600.7, 1 000.7, या यहाँ तक 1 600,7 के रूप में (देखें this Wikipedia पेज) प्रतिनिधित्व करते हैं।

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