2016-12-22 19 views
5

मैं .net port of libsodium का उपयोग कर रहा हूं।एक बाइट सरणी को स्ट्रिंग में कनवर्ट करना और फिर फिर से अलग-अलग परिणाम

public static byte[] ArgonHashBinary(string password, string salt, long opsLimit, int memLimit, long outputLength = ARGON_SALTBYTES) 

public static byte[] ArgonHashBinary(byte[] password, byte[] salt, long opsLimit, int memLimit, long outputLength = ARGON_SALTBYTES) 

क्या मैं के साथ समस्या हो रही है दोनों एक ही हैश उत्पादन जब इनपुट मान समान हैं रूपों है: हैश पीढ़ी समारोह दो रूपों, एक कि बाइट सरणियों स्वीकार करता है और एक है कि तार को स्वीकार करता है।

var saltAsBytes = PasswordHash.ArgonGenerateSalt(); 
var saltAsString = Encoding.UTF8.GetString(saltAsBytes); 
var tmp = Encoding.UTF8.GetBytes(saltAsString); 

var hash1 = PasswordHash.ArgonHashBinary(password, saltAsString, 6, 134217728, 16); 
var hash2 = PasswordHash.ArgonHashBinary(Encoding.UTF8.GetBytes(password), saltAsBytes, 6, 134217728, 16); 

"पासवर्डशैश" के साथ कुछ भी। libsodium है और मेरा कोड नहीं है।

उपरोक्त कोड से जब मैं इसे एक स्ट्रिंग से परिवर्तित करता हूं और फिर बाइट सरणी को बाइट सरणी में वापस ले जाता हूं। बाइट सरणी सरणी हमेशा एक अलग लंबाई है। ArgonGenerateSalt() 16 की लंबाई के साथ एक बाइट सरणी उत्पन्न करता है। जब मैं इसे आम तौर पर ~ 30 (विभिन्न नमक के उत्पादन के कारण अलग-अलग) के ऊपर एक स्ट्रिंग से वापस परिवर्तित करता हूं।

मैं यूटीएफ 8 में क्यों परिवर्तित हो रहा हूं? क्योंकि thats क्या वे आंतरिक रूप से कर रहे हैं: https://github.com/adamcaudill/libsodium-net/blob/master/libsodium-net/PasswordHash.cs

public static byte[] ArgonHashBinary(string password, string salt, StrengthArgon limit = StrengthArgon.Interactive, long outputLength = ARGON_SALTBYTES) 
    { 
     return ArgonHashBinary(Encoding.UTF8.GetBytes(password), Encoding.UTF8.GetBytes(salt), limit, outputLength); 
    } 

जब मैं एक UTF8 स्ट्रिंग हैशिंग समारोह असफल क्योंकि वे सुनिश्चित करें कि अपने 16 बाइट्स बनाने के लिए बाइट सरणी की लंबाई की जाँच कर रहे जाएगा नमक परिवर्तित। यदि मैं इसे एक ASCII स्ट्रिंग में परिवर्तित करता हूं तो यह काम करता है लेकिन एक अलग हैश (जो अपेक्षित है) उत्पन्न करता है।

इस कोड में हैशिंग टुकड़ा को स्पष्ट करने के लिए यह मुद्दा नहीं है। tmp क्यों अलग है तो saltAsBytes कुंजी है।

+0

आप 'PasswordHash में कोड एकल कदम रखा है यह देखने के लिए कि चीजें अलग-अलग कहां जा रही हैं? –

+0

@JimMischel कौन सा हिस्सा?उपरोक्त सबसे महत्वपूर्ण टुकड़ा तब होता है जब मैं नमक उत्पन्न करता हूं और फिर इसे एक स्ट्रिंग में घुमाता हूं और फिर एक बाइट सरणी में फिर से वापस ले जाता हूं। पाठ्यक्रम का अधिकांश कोड मेरा अपना है। लाइब्रेरी केवल एक चीज यादृच्छिक नमक का उत्पादन कर रही है। 'Tmp' चर के विषय में सबसे अधिक क्या है 'saltAsBytes' के समान नहीं है। तो मुझे नहीं लगता कि यह हैशिंग टुकड़े के साथ कुछ भी करने के लिए है। एक बार मुझे पता चला कि यह क्यों हो रहा है कि हैशिंग टुकड़ा शायद काम करेगा। – coding4fun

+0

क्या आप सुनिश्चित हैं कि बाइट सरणी में केवल वैध यूटीएफ -8 कोड हैं? मुझे यकीन नहीं है कि GetBytes() कैसे काम करता है, जब सरणी में अमान्य कोड बिंदु होते हैं। –

उत्तर

2

मुझे लगता है कि समस्या यह है कि ArgonGenerateSalt विधि UTF8 एन्कोडेड स्ट्रिंग को वापस नहीं करती है, यह returns completely random bytes है।

आप यूटीएफ 8 स्ट्रिंग के रूप में यादृच्छिक बाइट्स को डीकोड नहीं कर सकते हैं और इसे यात्रा के दौर की उम्मीद कर सकते हैं। 3 बाइट (विशेष रूप से 239, 191, 189) हो जाएगा

var data = new byte[] { 128 }; 
var dataAsString = Encoding.UTF8.GetString(data); 
var dataAsBytes = Encoding.UTF8.GetBytes(dataAsString); 

इस के बाद, dataAsBytes: देखने के लिए जहां यह ऊपर चल रही है एक तुच्छ उदाहरण का अनुसरण करना है।

+0

जो आपको लगता है कि 'ArgonHashBinary' के स्ट्रिंग संस्करण के लिए 'नमक' पैरामीटर लाइब्रेरी द्वारा कभी भी उत्पन्न नहीं किया जा सकता है। आपको इसे खुद का उत्पादन करना होगा। यदि सच एक खराब डिजाइन की तरह लगता है। – coding4fun

+0

@ कोडिंग 4fun यह निश्चित रूप से एक महत्वपूर्ण निरीक्षण प्रतीत होता है। – Kyle

2

स्ट्रिंग के लिए एक बाइट सरणी और फिर वापस फिर से उत्पादित विभिन्न परिणामों

एक बाइनरी डेटा परिवर्तित स्ट्रिंग में परिवर्तित नहीं किया जा सकता है और फिर वापस बाइट सरणी के बजाय Encoding.[AnyEncoding].GetBytes और Encoding.[AnyEncoding].GetString

का उपयोग कर Convert.ToBase64String और Convert.FromBase64String

आप आसानी से परीक्षण कर सकते हैं ...

var bytes = new byte[] { 255, 255, 255 }; 
var buf = Encoding.UTF8.GetString(bytes); 
var newbytes = Encoding.UTF8.GetBytes(buf); 

newbytes की लंबाई 9 हो जाएगा .....

संपादित करें: यह @Theo

के लिए परीक्षण का मामला है
var bytes = new byte[] { 0, 216 }; //any new byte[] { X, 216 }; 
var buf = Encoding.Unicode.GetString(bytes); 
var newbytes = Encoding.Unicode.GetBytes(buf); //253,255 
+0

असल में सवाल पूछने से पहले भी सोचा था लेकिन दुर्भाग्य से यह काम नहीं करता है। हैशिंग फ़ंक्शन में स्ट्रिंग को पास करते समय लंबाई होगी! = 16 जो 'SaltOutOfRangeException' अपवाद का कारण बनता है – coding4fun

+0

@ coding4fun मुझे आपका मतलब नहीं मिलता है लेकिन आपको स्ट्रिंग और आर्बिट्रे बाइनरी डेटा के बीच * रिवर्सबल * फ़ंक्शन की आवश्यकता होगी .... एन्कोडिंग का उपयोग करना सही तरीका नहीं है ... आपके पास अन्य विकल्प हैं जैसे 'बिटकोनवर्टर। टॉस्ट्रिंग' या 'सोपहेक्सबाइनरी' लेकिन बेस 64 एन्कोडिंग सबसे प्राकृतिक है ... –

+0

@ कोडिंग 4fun बीटीडब्लू: आपको बाइट सरणी को एन्कोड करना चाहिए लंबाई 16 और बेस 64 स्ट्रिंग में कनवर्ट करें ... इसके विपरीत एक 16 बाइट बाइट सरणी –

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