private static void SimulateReceiver() { var simpleMessage = GetRequest(); IJWTService jwtService = new RSAJWTService(); var rsaPrivateKeySet2Contents = File.ReadAllText($@"{LocalFileStorePath}\keys\rsa-prv-key-set2.key"); // Checking if JWT signature is valid var validationParameters = BuildValidationParameters(); var receivedJWT = simpleMessage.AuthorizationHeader; var receivedContent = simpleMessage.BodyContents; var jwtIsValid = jwtService.ValidateJWTRSA(receivedJWT, RSAPublicKeySet1Contents, "RS256", validationParameters); // Senders public key Console.WriteLine($"JWT validation={jwtIsValid}"); // Decoding if sinature is valid var jwtReread = jwtService.ReadJWTRSA(receivedJWT, RSAPublicKeySet1Contents, "RS256", validationParameters); // Senders public key Console.WriteLine($"serializedJWTReread:{jwtReread}"); var contentHashBase64 = jwtReread.Payload.Claims.Where(c => c.Type == "content_hash_base64").Single().Value; // Assuming that it always has data var contentHashAlgorithm = jwtReread.Payload.Claims.Where(c => c.Type == "content_hash_algorithm").Single().Value; // Assuming that it always has data var encryptedSecretBase64 = jwtReread.Payload.Claims.Where(c => c.Type == "encrypted_secret_base64").Single().Value; // Assuming that it always has data var encryptedSaltBase64 = jwtReread.Payload.Claims.Where(c => c.Type == "encrypted_salt_base64").Single().Value; // Assuming that it always has data Console.WriteLine($"encryptedKeyBase64={encryptedSecretBase64}"); // Note: The private key from set2 should only be held by opposing party, and never exchanged, as with all private keys var secret = jwtService.Decrypt(encryptedSecretBase64, rsaPrivateKeySet2Contents); // Receivers private key var salt = jwtService.Decrypt(encryptedSaltBase64, rsaPrivateKeySet2Contents); // Receivers private key Console.WriteLine($"secret={secret}"); Console.WriteLine($"salt={salt}"); Console.WriteLine($"secret.Length={secret.Length}"); var decryptedMessage = SymmetricCryptoService.Decrypt(receivedContent, Encoding.UTF8.GetBytes(secret), Encoding.UTF8.GetBytes(salt)); if (decryptedMessage != null && decryptedMessage.Length > 100) { Console.WriteLine($"decryptedMessage={decryptedMessage.Substring(0,100)}"); } else { Console.WriteLine($"decryptedMessage (chunked)={decryptedMessage}"); } Console.WriteLine("decryptedMessage.length=" + decryptedMessage.Length); Console.WriteLine($"contentHashBase64={contentHashBase64}"); //string hexContentHash = BitConverter.ToString(Convert.FromBase64String(contentHashBase64)).Replace("-", ""); //Console.WriteLine($"contentHashHex={hexContentHash}"); // Validate content hash var hashAlgorithm = HashAlgorithmEnum.Parse <HashAlgorithmEnum>(contentHashAlgorithm); if (!jwtService.ValidateBase64Hash(decryptedMessage, contentHashBase64, hashAlgorithm)) { //if(!jwtService.ValidateHexHash(decryptedContent, hexContentHash, hashAlgorithm)) { Console.Error.WriteLine("The content hash has been corrupted, do not continue to use these data!"); SendErrorReply("The content hash has been corrupted, do not continue to use these data!"); } else { Console.WriteLine("JWT was valid and hash was intact!"); SendOKReply("JWT was valid and hash was intact!"); } }
/* Konstruktor */ public Hasher(HashAlgorithmEnum algorithm) { switch (algorithm) { case HashAlgorithmEnum.SHA160: this.hashObject = new SHA1Managed(); break; case HashAlgorithmEnum.SHA256: this.hashObject = new SHA256Managed(); break; case HashAlgorithmEnum.SHA384: this.hashObject = new SHA384Managed(); break; case HashAlgorithmEnum.SHA512: this.hashObject = new SHA512Managed(); break; case HashAlgorithmEnum.MD5: this.hashObject = new MD5CryptoServiceProvider(); break; case HashAlgorithmEnum.HMACSHA1: this.hashObject = new HMACSHA1(); break; case HashAlgorithmEnum.MACTripleDES: this.hashObject = new MACTripleDES(); break; } }
/// <summary> /// Get the <see cref="HashAlgorithm"/> associated to the <see cref="HashAlgorithmEnum"/> /// </summary> /// <param name="algorithm">Algorithm request</param> /// <returns></returns> static public HashAlgorithm GetAlgorithm(HashAlgorithmEnum algorithm) { switch (algorithm) { case HashAlgorithmEnum.MD5: return(MD5.Create()); case HashAlgorithmEnum.SHA1: return(SHA1.Create()); case HashAlgorithmEnum.SHA256: return(SHA256.Create()); case HashAlgorithmEnum.SHA384: return(SHA384.Create()); case HashAlgorithmEnum.SHA512: return(SHA512.Create()); case HashAlgorithmEnum.RIPEMD160: return(RIPEMD160.Create()); case HashAlgorithmEnum.KeyedHashAlgorithm: return(KeyedHashAlgorithm.Create()); default: return(SHA256.Create()); } }
public int Load(byte[] buffer, long offset) { long value; BufferTools.ReadNumberFromBuffer(buffer, offset, num_bytes, out value); if (Enum.IsDefined(typeof(HashAlgorithmEnum), value)) { this.value = (HashAlgorithmEnum)value; } return(num_bytes); }
public string GenerateBase64Hash(string data, HashAlgorithmEnum algorithm) { if (algorithm == HashAlgorithmEnum.SHA512) { using (SHA512 sha = new SHA512Managed()) { var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(data)); return(Convert.ToBase64String(hash)); } } throw new Exception("Unsupported hashing algorithm!"); }
public string GenerateHexHash(string data, HashAlgorithmEnum algorithm) { if (algorithm == HashAlgorithmEnum.SHA512) { using (SHA512 sha = new SHA512Managed()) { var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(data)); string hexHash = BitConverter.ToString(hash).Replace("-", string.Empty); return(hexHash); } } throw new Exception("Unsupported hashing algorithm!"); }
public bool ValidateHexHash(string data, string hexHash, HashAlgorithmEnum algorithm) { if (algorithm == HashAlgorithmEnum.SHA512) { using (SHA512 sha = new SHA512Managed()) { var newHash = sha.ComputeHash(Encoding.UTF8.GetBytes(data)); string newHexHash = BitConverter.ToString(newHash).Replace("-", string.Empty); Console.WriteLine($"newHexHash={newHexHash}"); return(hexHash.ToUpper().Equals(newHexHash.ToUpper())); } } throw new Exception("Unsupported hashing algorithm!"); }
public bool ValidateBase64Hash(string data, string base64Hash, HashAlgorithmEnum algorithm) { if (algorithm == HashAlgorithmEnum.SHA512) { using (SHA512 sha = new SHA512Managed()) { var newHash = sha.ComputeHash(Encoding.UTF8.GetBytes(data)); String newBase64Hash = Convert.ToBase64String(newHash); Console.WriteLine($"newBase64Hash={newBase64Hash}"); return(base64Hash.Equals(newBase64Hash)); } } throw new Exception("Unsupported hashing algorithm!"); }
/// <summary> /// Hash string /// </summary> /// <param name="rawText"></param> /// <param name="hashAlgorithm"></param> /// <param name="encoding"></param> /// <returns>Hashed string in UPPERCASE</returns> /// <exception cref="NotSupportedException"></exception> public static string Hash(string rawText, HashAlgorithmEnum hashAlgorithm, Encoding encoding = null) { HashAlgorithmCreator hashCreator; switch (hashAlgorithm) { case HashAlgorithmEnum.MD5: hashCreator = MD5.Create; break; case HashAlgorithmEnum.SHA1: hashCreator = SHA1.Create; break; case HashAlgorithmEnum.SHA256: hashCreator = SHA256.Create; break; case HashAlgorithmEnum.SHA384: hashCreator = SHA384.Create; break; case HashAlgorithmEnum.SHA512: hashCreator = SHA512.Create; break; default: throw new NotSupportedException(); } if (encoding == null) { encoding = Encoding.UTF8; } using (var hashAlgorithmInstance = hashCreator()) { byte[] inputBytes = encoding.GetBytes(rawText); byte[] hashBytes = hashAlgorithmInstance.ComputeHash(inputBytes); // Convert the byte array to hexadecimal string StringBuilder sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append(hashBytes[i].ToString("X2")); } return(sb.ToString()); } }
/// <summary> /// Get the hash of a <see cref="byte"/> array with the <see cref="HashAlgorithmEnum"/> /// </summary> /// <param name="arrayByte"><see cref="byte"/> array to hash</param> /// <param name="algorithm">Hash algorithme</param> /// <param name="iteration">Number of iteration of the hash</param> /// <returns></returns> static public string Digest(HashAlgorithmEnum algorithm, byte[] arrayByte, int iteration) { if (iteration < 1) { iteration = 1; } using (HashAlgorithm algo = GetAlgorithm(algorithm)) { for (int i = 0; i < iteration; i++) { arrayByte = algo.ComputeHash(arrayByte); } return(arrayByte.HexToString()); } }
/// <summary> /// Initializes a new instance of the <see cref="CreateSessionParameters" /> class. /// </summary> /// <param name="LoginSalt">The salt to use when creating a session (required).</param> /// <param name="SaltPassword">Whether you have to use the UserSalt to create the password hash when logging in via the SaltedLogin method (required).</param> /// <param name="UserSalt">The password salt for the particular user (required).</param> /// <param name="UsePasswordHashes">Whether you have to hash the password with the given algorithm before it is combined with the login salt or not (required).</param> /// <param name="HashAlgorithm">The hash algorithm to use when generating the password hash (required).</param> public CreateSessionParameters(string LoginSalt = default(string), bool?SaltPassword = default(bool?), string UserSalt = default(string), bool?UsePasswordHashes = default(bool?), HashAlgorithmEnum HashAlgorithm = default(HashAlgorithmEnum)) { // to ensure "LoginSalt" is required (not null) if (LoginSalt == null) { throw new InvalidDataException("LoginSalt is a required property for CreateSessionParameters and cannot be null"); } else { this.LoginSalt = LoginSalt; } // to ensure "SaltPassword" is required (not null) if (SaltPassword == null) { throw new InvalidDataException("SaltPassword is a required property for CreateSessionParameters and cannot be null"); } else { this.SaltPassword = SaltPassword; } // to ensure "UserSalt" is required (not null) if (UserSalt == null) { throw new InvalidDataException("UserSalt is a required property for CreateSessionParameters and cannot be null"); } else { this.UserSalt = UserSalt; } // to ensure "UsePasswordHashes" is required (not null) if (UsePasswordHashes == null) { throw new InvalidDataException("UsePasswordHashes is a required property for CreateSessionParameters and cannot be null"); } else { this.UsePasswordHashes = UsePasswordHashes; } // to ensure "HashAlgorithm" is required (not null) if (HashAlgorithm == null) { throw new InvalidDataException("HashAlgorithm is a required property for CreateSessionParameters and cannot be null"); } else { this.HashAlgorithm = HashAlgorithm; } }
/// <summary> /// Girilen parametrelere gore plainText in ozetini alip byte[] olarak doner. /// </summary> /// <param name="plainText">Ozeti alinacak metin</param> /// <param name="hashAlgorithm">Ozet algoritmasi</param> /// <param name="stringConversion">Tuzlama degerini byte[] e cevirmek icin kullanilacak yontem</param> /// <returns>Parametre olarak verilen acik metnin ozet bilgisini string olarak doner.</returns> public string ComputeHash(string plainText, HashAlgorithmEnum hashAlgorithm, StringConversionEnum stringConversion = StringConversionEnum.Base64) { // Convert result into a base64-encoded string. var hashValue = string.Empty; if (stringConversion == StringConversionEnum.Base64) { hashValue = Convert.ToBase64String(ComputeHash(plainText, hashAlgorithm, string.Empty)); } else if (stringConversion == StringConversionEnum.Hex) { hashValue = ByteArrayToHexString(ComputeHash(plainText, hashAlgorithm, string.Empty)); } // Return the result. return(hashValue); }
/// <summary> /// Make hash with salt (stored at the end) /// </summary> /// <param name="text"> /// Original text /// </param> /// <param name="hashAlgorithm"> /// Hash algorithm: MD5, SHA1, SHA256, SHA384, SHA512 (default MD5) /// </param> /// <param name="useSalt"> /// Use salt for generate hash /// </param> /// <param name="saltBytes"> /// Salt bytes (if missing, use random salt) /// </param> /// <returns> /// Hash value formatted as a base64-encoded string. /// </returns> public static string ComputeHash(string text, HashAlgorithmEnum hashAlgorithm = HashAlgorithmEnum.MD5, bool useSalt = true, byte[] saltBytes = null) { if (text != String.Empty) { string hashValue = ""; HashAlgorithm hash; switch (hashAlgorithm) { case HashAlgorithmEnum.SHA1: hash = new SHA1Managed(); break; case HashAlgorithmEnum.SHA256: hash = new SHA256Managed(); break; case HashAlgorithmEnum.SHA384: hash = new SHA384Managed(); break; case HashAlgorithmEnum.SHA512: hash = new SHA512Managed(); break; default: hash = new MD5CryptoServiceProvider(); break; } if (useSalt) { if (saltBytes == null) { int minSaltSize = 4; int maxSaltSize = 8; saltBytes = new byte[(new System.Random()).Next(minSaltSize, maxSaltSize)]; RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetNonZeroBytes(saltBytes); } byte[] plainTextBytes = Encoding.UTF8.GetBytes(text); byte[] plainTextWithSaltBytes = new byte[plainTextBytes.Length + saltBytes.Length]; for (int i = 0; i < plainTextBytes.Length; i++) plainTextWithSaltBytes[i] = plainTextBytes[i]; for (int i = 0; i < saltBytes.Length; i++) plainTextWithSaltBytes[plainTextBytes.Length + i] = saltBytes[i]; byte[] hashBytes = hash.ComputeHash(plainTextWithSaltBytes); byte[] hashWithSaltBytes = new byte[hashBytes.Length + saltBytes.Length]; for (int i = 0; i < hashBytes.Length; i++) hashWithSaltBytes[i] = hashBytes[i]; for (int i = 0; i < saltBytes.Length; i++) hashWithSaltBytes[hashBytes.Length + i] = saltBytes[i]; hashValue = Convert.ToBase64String(hashWithSaltBytes); } else { hashValue = Convert.ToBase64String(hash.ComputeHash(Encoding.UTF8.GetBytes(text))); } return hashValue; } else return null; }
private static byte[] ComputeHash(this HashAlgorithmEnum hashHashAlgo, byte[] input) { HashAlgorithm hashAlgorithm = null; switch (hashHashAlgo) { case HashAlgorithmEnum.Md5: hashAlgorithm = MD5.Create(); break; case HashAlgorithmEnum.Sha1: hashAlgorithm = SHA1.Create(); break; case HashAlgorithmEnum.Sha2256: hashAlgorithm = SHA256.Create(); break; case HashAlgorithmEnum.Sha2384: hashAlgorithm = SHA384.Create(); break; case HashAlgorithmEnum.Sha2512: hashAlgorithm = SHA512.Create(); break; } return(hashAlgorithm?.ComputeHash(input)); }
private static byte[] ComputeHmac(this HashAlgorithmEnum algorithm, byte[] key, byte[] input) { KeyedHashAlgorithm hmacAlgo = new HMACMD5(); switch (algorithm) { case HashAlgorithmEnum.Md5: hmacAlgo = new HMACMD5(key); break; case HashAlgorithmEnum.Sha1: hmacAlgo = new HMACSHA1(key); break; case HashAlgorithmEnum.Sha2256: hmacAlgo = new HMACSHA256(key); break; case HashAlgorithmEnum.Sha2384: hmacAlgo = new HMACSHA384(key); break; case HashAlgorithmEnum.Sha2512: hmacAlgo = new HMACSHA512(key); break; } return(hmacAlgo.ComputeHash(input)); }
/// <summary> /// Belirtilen metnin ozetini alarak hashValue parametresi ile belirtilen ozet degeriyle karsilastirir. /// </summary> /// <param name="plainText">Ozeti alinip karsilastirilacak acik metin</param> /// <param name="hashAlgorithm">Ozet algoritmasi</param> /// <param name="hashValue">Mevcut ozet degeri</param> /// <param name="stringConversion">Hash degerini byte[] e cevirmek icin secilen yontem</param> /// <returns>Belirtilen hashValue degeri ile yeni hesaplanan ozet degerinin ayni olup olmadigi (true,false) bilgisini dondurur.</returns> public bool VerifyHash(string plainText, HashAlgorithmEnum hashAlgorithm, string hashValue, StringConversionEnum stringConversion = StringConversionEnum.Base64) { // Convert base64-encoded hash value into a byte array. byte[] hashWithSaltBytes = null; if (stringConversion == StringConversionEnum.Base64) { hashWithSaltBytes = Convert.FromBase64String(hashValue); } else if (stringConversion == StringConversionEnum.Hex) { hashWithSaltBytes = StringToByteArray(hashValue); } // We must know size of hash (without salt). int hashSizeInBits; // Size of hash is based on the specified algorithm. switch (hashAlgorithm) { case HashAlgorithmEnum.SHA1: hashSizeInBits = 160; break; case HashAlgorithmEnum.SHA256: hashSizeInBits = 256; break; case HashAlgorithmEnum.SHA384: hashSizeInBits = 384; break; case HashAlgorithmEnum.SHA512: hashSizeInBits = 512; break; case HashAlgorithmEnum.MD5: hashSizeInBits = 128; break; default: // Must be MD5 hashSizeInBits = 128; break; } // Convert size of hash from bits to bytes. var hashSizeInBytes = hashSizeInBits / 8; // Make sure that the specified hash value is long enough. if (hashWithSaltBytes.Length < hashSizeInBytes) { return(false); } // Allocate array to hold original salt bytes retrieved from hash. var saltBytes = new byte[hashWithSaltBytes.Length - hashSizeInBytes]; // Copy salt from the end of the hash to the new array. for (var i = 0; i < saltBytes.Length; i++) { saltBytes[i] = hashWithSaltBytes[hashSizeInBytes + i]; } // Compute a new hash string. var expectedHashString = string.Empty; if (stringConversion == StringConversionEnum.Base64) { expectedHashString = Convert.ToBase64String(ComputeHash(plainText, hashAlgorithm, Convert.ToBase64String(saltBytes))); } else if (stringConversion == StringConversionEnum.Hex) { expectedHashString = ByteArrayToHexString(ComputeHash(plainText, hashAlgorithm, ByteArrayToHexString(saltBytes))); } // If the computed hash matches the specified hash, // the plain text value must be correct. return(hashValue == expectedHashString); }
/// <summary> /// Get the hash of a <see cref="Stream" /> with the <see cref="HashAlgorithmEnum"/> /// </summary> /// <param name="filePath">Path of the file to get hash</param> /// <param name="algorithm">Hash algorithme</param> /// <returns></returns> static public string DigestFile(HashAlgorithmEnum algorithm, string filePath) { return(DigestFile(algorithm, filePath, 1)); }
/// <summary> /// Get the hash of a <see cref="Stream" /> with the <see cref="HashAlgorithmEnum"/> /// </summary> /// <param name="stream"><see cref="Stream" /> to hash</param> /// <param name="algorithm">Hash algorithme</param> static public string Digest(HashAlgorithmEnum algorithm, Stream stream) { return(Digest(algorithm, stream, 1)); }
/// <summary> /// Get the hash of a <see cref="byte"/> array with the <see cref="HashAlgorithmEnum"/> /// </summary> /// <param name="arrayByte"><see cref="byte"/> array to hash</param> /// <param name="algorithm">Hash algorithme</param> static public string Digest(HashAlgorithmEnum algorithm, byte[] arrayByte) { return(Digest(algorithm, arrayByte, 1)); }
/// <summary> /// Get the hash of a <see cref="string"/> with the <see cref="HashAlgorithmEnum"/> /// </summary> /// <param name="text">string to hash</param> /// <param name="algorithm">Hash algorithme</param> /// <param name="iteration">Number of iteration of the hash</param> /// <returns></returns> static public string Digest(HashAlgorithmEnum algorithm, string text, int iteration) { return(Digest(algorithm, UTF8SansBomEncoding.Default.GetBytes(text), iteration)); }
/// <summary> /// Get the hash of a <see cref="string"/> with the <see cref="HashAlgorithmEnum"/> /// </summary> /// <param name="text">string to hash</param> /// <param name="algorithm">Hash algorithme</param> static public string Digest(HashAlgorithmEnum algorithm, string text) { return(Digest(algorithm, text, 1)); }
/// <summary> /// Girilen parametrelere gore plainText in ozetini alip byte[] olarak doner. /// </summary> /// <param name="plainText">Ozeti alinacak metin</param> /// <param name="hashAlgorithm">Ozet algoritmasi</param> /// <param name="saltValue">Tuzlama degeri</param> /// <param name="stringConversion">Tuzlama degerini byte[] e cevirmek icin kullanilacak yontem</param> /// <returns>Parametre olarak verilen acik metnin ozet bilgisini btye[] olarak doner.</returns> public byte[] ComputeHash(string plainText, HashAlgorithmEnum hashAlgorithm, string saltValue, StringConversionEnum stringConversion = StringConversionEnum.Base64) { // If salt is not specified, generate it on the fly. byte[] saltBytes = null; if (saltValue == null) { // Generate a random number for the size of the salt. var random = new Random(); var saltSize = random.Next(MinSaltSize, MaxSaltSize); // Allocate a byte array, which will hold the salt. saltBytes = new byte[saltSize]; // Initialize a random number generator. var rng = new RNGCryptoServiceProvider(); // Fill the salt with cryptographically strong byte values. rng.GetNonZeroBytes(saltBytes); } else { if (stringConversion == StringConversionEnum.Base64) { saltBytes = Convert.FromBase64String(saltValue); } else if (stringConversion == StringConversionEnum.Hex) { saltBytes = StringToByteArray(saltValue); } } // Convert plain text into a byte array. var plainTextBytes = Encoding.UTF8.GetBytes(plainText); // Allocate array, which will hold plain text and salt. var plainTextWithSaltBytes = new byte[plainTextBytes.Length + saltBytes.Length]; // Copy plain text bytes into resulting array. for (var i = 0; i < plainTextBytes.Length; i++) { plainTextWithSaltBytes[i] = plainTextBytes[i]; } // Append salt bytes to the resulting array. for (var i = 0; i < saltBytes.Length; i++) { plainTextWithSaltBytes[plainTextBytes.Length + i] = saltBytes[i]; } // Because we support multiple hashing algorithms, we must define // hash object as a common (abstract) base class. We will specify the // actual hashing algorithm class later during object creation. HashAlgorithm hash; // Initialize appropriate hashing algorithm class. switch (hashAlgorithm) { case HashAlgorithmEnum.SHA1: hash = new SHA1Managed(); break; case HashAlgorithmEnum.SHA256: hash = new SHA256Managed(); break; case HashAlgorithmEnum.SHA384: hash = new SHA384Managed(); break; case HashAlgorithmEnum.SHA512: hash = new SHA512Managed(); break; case HashAlgorithmEnum.MD5: hash = new MD5CryptoServiceProvider(); break; default: hash = new MD5CryptoServiceProvider(); break; } // Compute hash value of our plain text with appended salt. var hashBytes = hash.ComputeHash(plainTextWithSaltBytes); // Create array which will hold hash and original salt bytes. var hashWithSaltBytes = new byte[hashBytes.Length + saltBytes.Length]; // Copy hash bytes into resulting array. for (var i = 0; i < hashBytes.Length; i++) { hashWithSaltBytes[i] = hashBytes[i]; } // Append salt bytes to the result. for (var i = 0; i < saltBytes.Length; i++) { hashWithSaltBytes[hashBytes.Length + i] = saltBytes[i]; } return(hashWithSaltBytes); }
/// <summary> /// Get the hash of a <see cref="Stream" /> with the <see cref="HashAlgorithmEnum"/> /// </summary> /// <param name="filePath">Path of the file to get hash</param> /// <param name="algorithm">Hash algorithme</param> /// <param name="iteration">Number of iteration of the hash</param> /// <returns></returns> static public string DigestFile(HashAlgorithmEnum algorithm, string filePath, int iteration) { using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) return(Digest(algorithm, file, iteration)); }
/// <summary> /// Compare text and hash (with salt) /// </summary> /// <param name="text"> /// Text to compare /// </param> /// <param name="hashAlgorithm"> /// Hash algorithm /// </param> /// <param name="hashValue"> /// Base64-encoded hash value with salt at the end /// </param> /// <returns> /// True - text has same hash (with same salt) /// </returns> public static bool VerifyHash(string text, HashAlgorithmEnum hashAlgorithm = HashAlgorithmEnum.MD5, string hashValue = null) { if (hashValue != null) { byte[] hashWithSaltBytes = Convert.FromBase64String(hashValue); int hashSize; switch (hashAlgorithm) { case HashAlgorithmEnum.SHA1: hashSize = 160 / 8; break; case HashAlgorithmEnum.SHA256: hashSize = 256 / 8; break; case HashAlgorithmEnum.SHA384: hashSize = 384 / 8; break; case HashAlgorithmEnum.SHA512: hashSize = 512 / 8; break; default: hashSize = 128 / 8; break; // Default MD5 } if (hashWithSaltBytes.Length >= hashSize) { byte[] saltBytes = new byte[hashWithSaltBytes.Length - hashSize]; for (int i = 0; i < saltBytes.Length; i++) saltBytes[i] = hashWithSaltBytes[hashSize + i]; string expectedHashString = ComputeHash(text, hashAlgorithm, true, saltBytes); return (hashValue == expectedHashString); } else return false; } else return false; }