Sha256 के साथ एक स्ट्रिंग को हिट करना


141

मैं SHA256 का उपयोग करके एक स्ट्रिंग हैश करने की कोशिश कर रहा हूं, मैं निम्नलिखित कोड का उपयोग कर रहा हूं:

using System;
using System.Security.Cryptography;
using System.Text;
 public class Hash
    {
    public static string getHashSha256(string text)
    {
        byte[] bytes = Encoding.Unicode.GetBytes(text);
        SHA256Managed hashstring = new SHA256Managed();
        byte[] hash = hashstring.ComputeHash(bytes);
        string hashString = string.Empty;
        foreach (byte x in hash)
        {
            hashString += String.Format("{0:x2}", x);
        }
        return hashString;
    }
}

हालाँकि, यह कोड मेरे दोस्तों php, साथ ही ऑनलाइन जनरेटर (जैसे यह जनरेटर ) की तुलना में काफी अलग परिणाम देता है।

क्या किसी को पता है कि त्रुटि क्या है? विभिन्न आधार?


17
ऑफ टॉपिक लेकिन इस बात का ध्यान रखें कि StringBuilder बनाना और String.Format के बजाय अपने foreach लूप में AppendFormat का उपयोग करना आपके कोड को अनावश्यक रूप से बहुत सारी स्ट्रिंग ऑब्जेक्ट बनाने से रोकेगा।
मार्सेल लैमोथेव

जवाबों:


155

Encoding.Unicodeयूटीएफ -16 के लिए माइक्रोसॉफ्ट का भ्रामक नाम है (एक डबल-वाइड एन्कोडिंग, जिसका उपयोग ऐतिहासिक कारणों से विंडोज की दुनिया में किया जाता है लेकिन किसी और द्वारा उपयोग नहीं किया जाता है)। http://msdn.microsoft.com/en-us/library/system.text.encoding.unicode.aspx

यदि आप अपने bytesसरणी का निरीक्षण करते हैं , तो आप देखेंगे कि हर दूसरा बाइट 0x00(डबल-वाइड एन्कोडिंग के कारण) है।

आपको Encoding.UTF8.GetBytesइसके बजाय उपयोग करना चाहिए ।

लेकिन इसके अलावा, आप अलग-अलग परिणाम देखेंगे कि आप '\0'जिस डेटा को हैशिंग का हिस्सा मानते हैं, उसे समाप्त करने वाले बाइट को मानते हैं या नहीं । तीन बाइट्स हैशिंग से दो बाइट्स "Hi"को अलग करने से एक अलग परिणाम मिलेगा । आपको तय करना होगा कि आप क्या करना चाहते हैं। (संभवतः आप अपने मित्र का PHP कोड जो भी कर रहे हैं, करना चाहते हैं।)"Hi"

ASCII पाठ के लिए, Encoding.UTF8निश्चित रूप से उपयुक्त होगा। आप के लिए लक्ष्य कर रहे हैं सही अपने मित्र का कोड के साथ संगतता, यहां तक कि गैर- ASCII आदानों पर, तो आप बेहतर इस तरह के रूप में गैर- ASCII वर्ण के साथ कुछ परीक्षण मामलों की कोशिश करता हूँ éऔर और देखें कि क्या आपके परिणाम अभी भी मेल खाते हैं। यदि नहीं, तो आपको यह पता लगाना होगा कि आपका मित्र वास्तव में क्या उपयोग कर रहा है; यह 8-बिट "कोड पृष्ठों" में से एक हो सकता है जो यूनिकोड के आविष्कार से पहले लोकप्रिय हुआ करता था। (फिर से, मुझे लगता है कि विंडोज मुख्य कारण है कि किसी को अभी भी "कोड पृष्ठों" के बारे में चिंता करने की आवश्यकता है।)


3
@Elmue, आपको यह जानकर प्रसन्नता हो सकती है कि "UTF8-एन्कोडेड बाइट्स द्वारा छँटाई" और "यूनिकोड कोडपॉइंट्स द्वारा छँटाई" बराबर हैं! (जैसा कि "UTF16- एन्कोडेड shorts द्वारा सॉर्टिंग " है, लेकिन "UTF16-एन्कोडेड बाइट्स द्वारा सॉर्टिंग नहीं " जब तक कि आप एक बड़े-एंडियन सिस्टम पर नहीं हैं, जो कि विंडोज नहीं है।) हालांकि, यूनिकोड में "सॉर्टिंग" वास्तव में है। जटिल विषय जिसे एक और दिन के लिए सहेजा जाना चाहिए।
क्क्सप्लसोन नोव

2
@ इल्म आपके गलत उत्तरों में इतना आत्मविश्वास नहीं है। कोशिश करके देखो; आपको आश्चर्य होगा। चाहे आश्चर्य सुखद हो या अप्रिय पूरी तरह से आप पर निर्भर है। :)
क्क्सप्लसोन

2
@ इल्म, “ क्या होगा यदि आप एक मामले की असंवेदनशील तुलना करना चाहते हैं? यदि आप इस तरह का सामान करना चाहते हैं, तो आपको यूटीएफ -16 में बाइट्स बदलने की भी आवश्यकता है। तथ्य यह है कि यह निश्चित लंबाई है एक बिट में मदद नहीं करता है।
आर्टुरो टोरेस सेंचेज

2
"किसी और द्वारा उपयोग नहीं किया गया" काफी दिलचस्प दावा है, क्योंकि जावा आंतरिक रूप से तार को UTF-16 के रूप में भी संभालता है ...
सामी कुहोमेन 12

4
@Elmue "आपकी टिप्पणी गलत है: UTF16 यूनिकोड है।" तुम गलत हो। "यूनिकोड" एक मानक है जो ग्लिफ़ को संख्या (कोड अंक) प्रदान करता है। सरोगेट जोड़े को छोड़कर, यह बाइट के रूप में उन संख्याओं का प्रतिनिधित्व करने का तरीका नहीं बताता है। UTF16 कोड बिंदुओं को निर्दिष्ट करता है <-> बाइट्स। यूनिकोड ग्लिफ्स <-> कोड बिंदुओं को निर्दिष्ट करता है।
एंटिडुह

103

मुझे कार्यान्वयन की एक और शैली के साथ भी यह समस्या थी लेकिन मैं भूल गया कि मुझे यह कहां से मिला है क्योंकि यह 2 साल पहले था।

static string sha256(string randomString)
{
    var crypt = new SHA256Managed();
    string hash = String.Empty;
    byte[] crypto = crypt.ComputeHash(Encoding.ASCII.GetBytes(randomString));
    foreach (byte theByte in crypto)
    {
        hash += theByte.ToString("x2");
    }
    return hash;
}

जब मैं abcdefghi2013किसी कारण से कुछ इनपुट करता हूं तो यह मेरे लॉगिन मॉड्यूल में त्रुटियों के विभिन्न परिणाम और परिणाम देता है। फिर मैंने कोड को उसी तरह से संशोधित करने का प्रयास किया जैसा कि क्क्सप्लस द्वारा सुझाया गया था और एन्कोडिंग ASCIIको UTF8तब से बदल दिया गया था, तब आखिरकार यह काम कर गया!

static string sha256(string randomString)
{
    var crypt = new System.Security.Cryptography.SHA256Managed();
    var hash = new System.Text.StringBuilder();
    byte[] crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(randomString));
    foreach (byte theByte in crypto)
    {
        hash.Append(theByte.ToString("x2"));
    }
    return hash.ToString();
}

अद्भुत और विस्तृत जवाब के लिए फिर से क्क्सप्लसोन धन्यवाद! :)


आपके समाधान ने मेरे लिए काम किया। लेकिन मेरा मामला अलग है। यह sha512 के साथ है और कोड लाइन जिसने मेरी समस्या को हल किया है, hash += bit.ToString("x2");मैं यहाँ एक सवाल है: मैं Convert.ToBase64String(byte[] encryptedBytes)बाइट्स से स्ट्रिंग में वापस कन्वर्ट करने के लिए उपयोग कर रहा था । वह मुझे अलग परिणाम दे रहा था। तो बाइट्स से स्ट्रिंग में परिवर्तित करने के इन दो तरीकों के बीच क्या अलग है ..?
लंगलिया

क्या यहां कुछ अनुकूलन का उपयोग करना संभव है (जैसे कि मेरा स्वयं का आरंभीकरण वेक्टर) या केवल यादृच्छिक स्ट्रिंग को जोड़ना / प्रस्तुत करना है?
FrenkyB

मुझे वास्तव में यकीन नहीं है कि आपका क्या मतलब है। यह सिर्फ एक बहुत ही सरल हैशिंग फ़ंक्शन है और आप हमेशा इसे जोड़ सकते हैं / अनुकूलित कर सकते हैं, लेकिन आप चाहते हैं। यादृच्छिक स्ट्रिंग को जोड़कर / पूर्वनिर्मित करके क्या आपको नमस्कार करने का मतलब है? वैसे यह आगे की सुरक्षा के लिए इसे अनुकूलित करने का एक अच्छा तरीका है।
निको दमदम

पासवर्ड स्टोर करने के लिए कार्य कारक के बिना सिर्फ SHA हैशिंग का उपयोग करने की अनुशंसा नहीं की जाती है। दूसरे शब्दों में, पासवर्ड की हैशिंग प्रक्रिया काफी धीमी होनी चाहिए, ताकि हैकर्स को तेजी से अनुमान लगाने से रोका जा सके। बेहतर सुरक्षा के लिए Bcrypt, या Scrypt का उपयोग करें।
टन स्नोई

@TonSnoei हाँ यह सच है। हालांकि, यह कॉलेज में कुछ प्राचीन आंतरिक सिस्टम एप्लिकेशन से कुछ पुराना कोड है जो अब कोई भी उपयोग नहीं करता है और मैं वास्तव में खुद को इसकी सिफारिश नहीं करूंगा। इसके अलावा, यह धागा विशेष रूप से SHA256 एन्कोडिंग और सीधे पासवर्ड के बारे में नहीं है। हालाँकि, मुझे यह पसंद नहीं आएगा कि अगर वह आपके फैंस को गुदगुदाने लगे तो पासवर्ड के संदर्भ को हटा दें।
निको दमदम

6
public static string ComputeSHA256Hash(string text)
{
    using (var sha256 = new SHA256Managed())
    {
        return BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(text))).Replace("-", "");
    }                
}

अलग-अलग परिणाम प्राप्त करने का कारण यह है कि आप एक ही स्ट्रिंग एन्कोडिंग का उपयोग नहीं करते हैं। आपके द्वारा SHA256 की गणना करने वाली ऑन-लाइन वेब साइट के लिए डाला गया लिंक UTF8 एन्कोडिंग का उपयोग करता है, जबकि आपके उदाहरण में आपने यूनिकोड एनकोडिंग का उपयोग किया था। वे दो अलग-अलग एनकोडिंग हैं, इसलिए आपको एक ही परिणाम नहीं मिलता है। ऊपर दिए गए उदाहरण से आपको लिंक किए गए वेब साइट के समान SHA256 हैश मिल जाता है। आपको वही एन्कोडिंग भी PHP में उपयोग करने की आवश्यकता है।

एब्सोल्यूट मिनिमम हर सॉफ्टवेयर डेवलपर बिल्कुल, यूनिकोड और कैरेक्टर सेट्स (नो एक्सक्यूज़) के बारे में सकारात्मक रूप से जानना चाहिए!

https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/


4

PHP संस्करण में आप अंतिम पैरामीटर में 'सही' भेज सकते हैं, लेकिन डिफ़ॉल्ट 'गलत' है। पहले पैरामीटर के रूप में 'sha256' पास करते समय निम्न एल्गोरिथ्म डिफ़ॉल्ट PHP के हैश फ़ंक्शन के बराबर है:

public static string GetSha256FromString(string strData)
    {
        var message = Encoding.ASCII.GetBytes(strData);
        SHA256Managed hashString = new SHA256Managed();
        string hex = "";

        var hashValue = hashString.ComputeHash(message);
        foreach (byte x in hashValue)
        {
            hex += String.Format("{0:x2}", x);
        }
        return hex;
    }

4
मैं इसके बजाय प्रयोग ASCIIऔर नहीं करूंगा byte[] arrBytes = System.Text.Encoding.UTF8.GetBytes(strData)
c00000fd

3
public string EncryptPassword(string password, string saltorusername)
        {
            using (var sha256 = SHA256.Create())
            {
                var saltedPassword = string.Format("{0}{1}", salt, password);
                byte[] saltedPasswordAsBytes = Encoding.UTF8.GetBytes(saltedPassword);
                return Convert.ToBase64String(sha256.ComputeHash(saltedPasswordAsBytes));
            }
        }

1
मुझे यह तथ्य पसंद है कि आपने कुछ नमक ^ ^
फेबियन

1

सबसे छोटा और सबसे तेज़ तरीका। केवल 1 लाइन!

public static string StringSha256Hash(string text) =>
    string.IsNullOrEmpty(text) ? string.Empty : BitConverter.ToString(new System.Security.Cryptography.SHA256Managed().ComputeHash(System.Text.Encoding.UTF8.GetBytes(text))).Replace("-", string.Empty);

-2

यह मेरे लिए .NET Core 3.1 में काम करता है।
लेकिन .NET 5 पूर्वावलोकन 7 में नहीं।

using System;
using System.Security.Cryptography;
using System.Text;

namespace PortalAplicaciones.Shared.Models
{
    public class Encriptar
    {
        public static string EncriptaPassWord(string Password)
        {
            try
            {
                SHA256Managed hasher = new SHA256Managed();

                byte[] pwdBytes = new UTF8Encoding().GetBytes(Password);
                byte[] keyBytes = hasher.ComputeHash(pwdBytes);

                hasher.Dispose();
                return Convert.ToBase64String(keyBytes);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }  
    }
}
 

1
StackOverflow में आपका स्वागत है। कृपया कुछ स्पष्टीकरण प्रदान करें कि आपको क्यों लगता है कि आपका प्रस्तावित समाधान ओपी की समस्या को हल कर सकता है।
पीटर क्सला

1
कृपया अपवाद को फिर से फेंकने से बचने की कोशिश करें। इसके साथ आप मूल StackTrace को ढीला करते हैं।
पीटर क्सला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.