[C#] Sha256으로 문자열 해싱

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와 온라인 생성기 (예 : This generator ) 와 비교하여 상당히 다른 결과를 제공합니다

누구든지 오류가 무엇인지 알고 있습니까? 다른 기지?



답변

Encoding.UnicodeUTF-16 (역사적 이유로 Windows 세계에서는 사용되었지만 다른 사람은 사용하지 않는 이중 너비 인코딩)에 대한 Microsoft의 오해의 소지가 있습니다. http://msdn.microsoft.com/en-us/library/system.text.encoding.unicode.aspx

bytes배열 을 검사 하면 두 번째 바이트가 0x00(두 배 너비 인코딩 때문에) 모든 바이트임을 알 수 있습니다 .

Encoding.UTF8.GetBytes대신 사용해야합니다 .

또한 종료 '\0'바이트를 해시하는 데이터의 일부로 간주하는지 여부에 따라 다른 결과가 표시됩니다 . 두 바이트 "Hi"를 해시하면 바이트 를 해시하는 것과 다른 결과가 나타납니다 "Hi". 원하는 것을 결정해야합니다. (아마도 친구의 PHP 코드 중 하나를 수행하려고합니다.)

ASCII 텍스트의 경우 Encoding.UTF8확실히 적합합니다. 당신이 목표라면 완벽한 심지어 비 ASCII 입력에, 친구의 코드와의 호환성, 당신은 더 나은 같은 비 ASCII 문자와 몇 가지 테스트 케이스를 시도 할 것입니다 é당신의 결과는 여전히 일치 여부를 참조하십시오. 그렇지 않은 경우 친구가 실제로 사용하는 인코딩을 파악해야합니다. 유니 코드가 발명되기 전에 널리 사용되었던 8 비트 “코드 페이지”중 하나 일 수 있습니다. (또, Windows는 누구나 “코드 페이지”에 대해 여전히 걱정해야하는 주된 이유라고 생각합니다.)


답변

나는 또 다른 스타일의 구현 으로이 문제를 겪었지만 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어떤 이유로 든 같은 것을 입력 하면 다른 결과가 나오고 로그인 모듈에 오류가 발생합니다. 그런 다음 Quuxplusone이 제안한 것과 같은 방식으로 코드를 수정하려고 시도했으며 인코딩을에서 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();
}

훌륭하고 자세한 답변을 위해 다시 Quuxplusone에 감사드립니다! 🙂


답변

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/


답변

PHP 버전에서는 마지막 매개 변수에서 ‘true’를 보낼 수 있지만 기본값은 ‘false’입니다. 다음 알고리즘은 첫 번째 매개 변수로 ‘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;
    }


답변

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));
            }
        }


답변

가장 짧고 빠른 방법. 단 한 줄!

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);


답변

이것은 .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);
            }
        }
    }
}