Używam następującego kodu C # do obliczenia skrótu MD5 z ciągu. Działa dobrze i generuje 32-znakowy ciąg szesnastkowy w następujący sposób:
900150983cd24fb0d6963f7d28e17f72
string sSourceData;
byte[] tmpSource;
byte[] tmpHash;
sSourceData = "MySourceData";
//Create a byte array from source data.
tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);
tmpHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);
// and then convert tmpHash to string...
Czy istnieje sposób na użycie takiego kodu do wygenerowania 16-znakowego ciągu szesnastkowego (lub 12-znakowego)? 32-znakowy ciąg szesnastkowy jest dobry, ale myślę, że wprowadzanie kodu przez klienta będzie nudne!
// given, a password in a string string password = @"1234abcd"; // byte array representation of that string byte[] encodedPassword = new UTF8Encoding().GetBytes(password); // need MD5 to calculate the hash byte[] hash = ((HashAlgorithm) CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedPassword); // string representation (similar to UNIX format) string encoded = BitConverter.ToString(hash) // without dashes .Replace("-", string.Empty) // make lowercase .ToLower(); // encoded contains the hash you want
źródło
BitConverter
nie działa w ten sam sposób w systemie Windows i Linux, zobacz to pytanie: stackoverflow.com/questions/11454004/ ...Próbowałem utworzyć ciąg reprezentujący wartość skrótu MD5 za pomocą LINQ, jednak żadna z odpowiedzi nie była rozwiązaniami LINQ, dlatego dodano to do największej liczby dostępnych rozwiązań.
string result; using (MD5 hash = MD5.Create()) { result = String.Join ( "", from ba in hash.ComputeHash ( Encoding.UTF8.GetBytes(observedText) ) select ba.ToString("x2") ); }
źródło
return string.Join( "", hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );
return string.Concat( hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );
zamiast tego. Jest trochę krótszy, prawdopodobnie jaśniejszy zamiar i działa nieznacznie szybciej (<10% wzrost wydajności).Zależy całkowicie od tego, co próbujesz osiągnąć. Technicznie rzecz biorąc, możesz po prostu wziąć pierwsze 12 znaków z wyniku skrótu MD5, ale specyfikacja MD5 polega na wygenerowaniu 32-znakowego znaku.
Zmniejszenie rozmiaru skrótu zmniejsza bezpieczeństwo i zwiększa ryzyko kolizji i uszkodzenia systemu.
Być może, jeśli powiesz nam więcej o tym, co próbujesz osiągnąć, będziemy mogli pomóc więcej.
źródło
Możesz użyć
Convert.ToBase64String
do konwersji 16-bajtowego wyjścia MD5 na ~ 24-znakowy łańcuch. Trochę lepiej bez zmniejszania bezpieczeństwa. (j9JIbSY8HuT89/pwdC8jlw==
na przykład)źródło
Obsługuje ciąg i strumień plików.
przykłady
string hashString = EasyMD5.Hash("My String"); string hashFile = EasyMD5.Hash(System.IO.File.OpenRead("myFile.txt"));
-
class EasyMD5 { private static string GetMd5Hash(byte[] data) { StringBuilder sBuilder = new StringBuilder(); for (int i = 0; i < data.Length; i++) sBuilder.Append(data[i].ToString("x2")); return sBuilder.ToString(); } private static bool VerifyMd5Hash(byte[] data, string hash) { return 0 == StringComparer.OrdinalIgnoreCase.Compare(GetMd5Hash(data), hash); } public static string Hash(string data) { using (var md5 = MD5.Create()) return GetMd5Hash(md5.ComputeHash(Encoding.UTF8.GetBytes(data))); } public static string Hash(FileStream data) { using (var md5 = MD5.Create()) return GetMd5Hash(md5.ComputeHash(data)); } public static bool Verify(string data, string hash) { using (var md5 = MD5.Create()) return VerifyMd5Hash(md5.ComputeHash(Encoding.UTF8.GetBytes(data)), hash); } public static bool Verify(FileStream data, string hash) { using (var md5 = MD5.Create()) return VerifyMd5Hash(md5.ComputeHash(data), hash); } }
źródło
Przypuszczam, że lepiej jest użyć kodowania UTF-8 w ciągu MD5.
public static string MD5(this string s) { using (var provider = System.Security.Cryptography.MD5.Create()) { StringBuilder builder = new StringBuilder(); foreach (byte b in provider.ComputeHash(Encoding.UTF8.GetBytes(s))) builder.Append(b.ToString("x2").ToLower()); return builder.ToString(); } }
źródło
Skrót MD5 ma 128 bitów, więc nie można go przedstawić w postaci szesnastkowej z mniej niż 32 znakami ...
źródło
System.Text.StringBuilder hash = new System.Text.StringBuilder(); System.Security.Cryptography.MD5CryptoServiceProvider md5provider = new System.Security.Cryptography.MD5CryptoServiceProvider(); byte[] bytes = md5provider.ComputeHash(new System.Text.UTF8Encoding().GetBytes(YourEntryString)); for (int i = 0; i < bytes.Length; i++) { hash.Append(bytes[i].ToString("x2")); //lowerCase; X2 if uppercase desired } return hash.ToString();
źródło
Szybsza alternatywa istniejącej odpowiedzi dla .NET Core 2.1 i nowszych:
public static string CreateMD5(string s) { using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create()) { var encoding = Encoding.ASCII; var data = encoding.GetBytes(s); Span<byte> hashBytes = stackalloc byte[16]; md5.TryComputeHash(data, hashBytes, out int written); if(written != hashBytes.Length) throw new OverflowException(); Span<char> stringBuffer = stackalloc char[32]; for (int i = 0; i < hashBytes.Length; i++) { hashBytes[i].TryFormat(stringBuffer.Slice(2 * i), out _, "x2"); } return new string(stringBuffer); } }
Możesz zoptymalizować go jeszcze bardziej, jeśli masz pewność, że twoje ciągi są wystarczająco małe i zastąp kodowanie. GetBytes przez alternatywę unsafe int GetBytes (ReadOnlySpan chars, Span bytes).
źródło
To rozwiązanie wymaga języka C # 8 i korzysta z
Span<T>
. Uwaga, w razie potrzeby nadal będziesz musiał zadzwonić,.Replace("-", string.Empty).ToLowerInvariant()
aby sformatować wynik.public static string CreateMD5(ReadOnlySpan<char> input) { var encoding = System.Text.Encoding.UTF8; var inputByteCount = encoding.GetByteCount(input); using var md5 = System.Security.Cryptography.MD5.Create(); Span<byte> bytes = inputByteCount < 1024 ? stackalloc byte[inputByteCount] : new byte[inputByteCount]; Span<byte> destination = stackalloc byte[md5.HashSize / 8]; encoding.GetBytes(input, bytes); // checking the result is not required because this only returns false if "(destination.Length < HashSizeValue/8)", which is never true in this case md5.TryComputeHash(bytes, destination, out int _bytesWritten); return BitConverter.ToString(destination.ToArray()); }
źródło
https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.md5?view=netframework-4.7.2
using System; using System.Security.Cryptography; using System.Text; static string GetMd5Hash(string input) { using (MD5 md5Hash = MD5.Create()) { // Convert the input string to a byte array and compute the hash. byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input)); // Create a new Stringbuilder to collect the bytes // and create a string. StringBuilder sBuilder = new StringBuilder(); // Loop through each byte of the hashed data // and format each one as a hexadecimal string. for (int i = 0; i < data.Length; i++) { sBuilder.Append(data[i].ToString("x2")); } // Return the hexadecimal string. return sBuilder.ToString(); } } // Verify a hash against a string. static bool VerifyMd5Hash(string input, string hash) { // Hash the input. string hashOfInput = GetMd5Hash(input); // Create a StringComparer an compare the hashes. StringComparer comparer = StringComparer.OrdinalIgnoreCase; return 0 == comparer.Compare(hashOfInput, hash); }
źródło
Chciałbym zaoferować alternatywę, która wydaje się działać co najmniej 10% szybciej niż odpowiedź craigdfrench w moich testach (.NET 4.7.2):
public static string GetMD5Hash(string text) { using ( var md5 = MD5.Create() ) { byte[] computedHash = md5.ComputeHash( Encoding.UTF8.GetBytes(text) ); return new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(computedHash).ToString(); } }
Jeśli wolisz mieć
using System.Runtime.Remoting.Metadata.W3cXsd2001;
na górze, treść metody może być łatwiejsza do odczytania w jednym wierszu:using ( var md5 = MD5.Create() ) { return new SoapHexBinary( md5.ComputeHash( Encoding.UTF8.GetBytes(text) ) ).ToString(); }
Dość oczywiste, ale dla kompletności, w kontekście OP byłby używany jako:
sSourceData = "MySourceData"; tmpHash = GetMD5Hash(sSourceData);
źródło
Oto moja funkcja narzędziowa dla
UTF8
, którą można wASCII
razie potrzeby zastąpić :public static byte[] MD5Hash(string message) { return MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(message)); }
źródło
StringBuilder sb= new StringBuilder(); for (int i = 0; i < tmpHash.Length; i++) { sb.Append(tmpHash[i].ToString("x2")); }
źródło
Idk cokolwiek o 16-znakowych ciągach szesnastkowych ...
using System; using System.Security.Cryptography; using System.Text;
Ale tutaj jest mój do tworzenia skrótu MD5 w jednej linii.
string hash = BitConverter.ToString(MD5.Create().ComputeHash(Encoding.ASCII.GetBytes("THIS STRING TO MD5"))).Replace("-","");
źródło