using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security;
using System.Security.Cryptography;
namespace FMISLayer.Service
{
public class clsSecurityService
{
///
/// base64-encoded result. Before the hash is computed, a random salt
/// is generated and appended to the plain text. This salt is stored at
/// the end of the hash value, so it can be used later for hash
/// verification.
///
////// Plaintext value to be hashed. The function does not check whether
/// this parameter is null.
/// ////// Name of the hash algorithm. Allowed values are: “MD5”, “SHA1”,
/// “SHA256”, “SHA384”, and “SHA512” (if any other value is specified
/// MD5 hashing algorithm will be used). This value is case-insensitive.
/// ///
/// Hash value formatted as a base64-encoded string.
///
public static string ComputeHash(string plainText, string hashAlgorithm)
{
// Convert plain text into a byte array.
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
// 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;
// Make sure hashing algorithm name is specified.
if (hashAlgorithm == null)
hashAlgorithm = “”;
// Initialize appropriate hashing algorithm class.
switch (hashAlgorithm.ToUpper())
{
case “SHA1”:
hash = new SHA1Managed();
break;
case “SHA256”:
hash = new SHA256Managed();
break;
case “SHA384”:
hash = new SHA384Managed();
break;
case “SHA512”:
hash = new SHA512Managed();
break;
default:
hash = new MD5CryptoServiceProvider();
break;
}
// Compute hash value of our plain text with appended salt.
byte[] hashBytes = hash.ComputeHash(plainTextBytes);
// Convert result into a base64-encoded string.
string hashValue = Convert.ToBase64String(hashBytes);
// Return the result.
return hashValue;
}
///
/// value.
///
////// Plain text to be verified against the specified hash. The function
/// does not check whether this parameter is null.
/// ////// Name of the hash algorithm. Allowed values are: “MD5”, “SHA1”,
/// “SHA256”, “SHA384”, and “SHA512” (if any other value is specified,
/// MD5 hashing algorithm will be used). This value is case-insensitive.
/// ////// Base64-encoded hash value produced by ComputeHash function. This value
/// includes the original salt appended to it.
/// ///
/// If computed hash mathes the specified hash the function the return
/// value is true; otherwise, the function returns false.
///
public static bool VerifyHash(string plainText,string hashAlgorithm,string hashValue)
{
byte[] hashWithSaltBytes;
try
{
// Convert base64-encoded hash value into a byte array.
hashWithSaltBytes = Convert.FromBase64String(hashValue);
}
catch
{
return false;
}
// We must know size of hash (without salt).
int hashSizeInBits, hashSizeInBytes;
// Make sure that hashing algorithm name is specified.
if (hashAlgorithm == null)
hashAlgorithm = “”;
// Size of hash is based on the specified algorithm.
switch (hashAlgorithm.ToUpper())
{
case “SHA1”:
hashSizeInBits = 160;
break;
case “SHA256”:
hashSizeInBits = 256;
break;
case “SHA384”:
hashSizeInBits = 384;
break;
case “SHA512”:
hashSizeInBits = 512;
break;
default: // Must be MD5
hashSizeInBits = 128;
break;
}
// Convert size of hash from bits to bytes.
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.
byte[] saltBytes = new byte[hashWithSaltBytes.Length –
hashSizeInBytes];
// Copy salt from the end of the hash to the new array.
for (int i = 0; i < saltBytes.Length; i++)
saltBytes[i] = hashWithSaltBytes[hashSizeInBytes + i];
// Compute a new hash string.
string expectedHashString = ComputeHash(plainText, hashAlgorithm);
// If the computed hash matches the specified hash,
// the plain text value must be correct.
return (hashValue == expectedHashString);
}
}
}