/// <summary> /// Create a hashed representation of the plain text. /// </summary> /// <param name="plainText">The text to hash</param> /// <param name="supportedHashAlgorithm">If supplied the algorithm to hash the plain text with. Otherwise default.</param> /// <param name="complexityThrottle"> /// Offers the ability to tune the algorithm in order to increase the complexity. 1 being /// the lowest value and 100 being very large. /// </param> /// <param name="saltProvider">Provider of the salt used for creating the hash.</param> private HashedValue(string plainText, SupportedHashAlgorithm supportedHashAlgorithm, int complexityThrottle, ICryptoProvider saltProvider) { _algorithm = supportedHashAlgorithm; _complexityThrottle = complexityThrottle; _saltProvider = saltProvider; ComputeHashWorker(plainText, supportedHashAlgorithm, complexityThrottle); }
/// <summary> /// Builds a SHA256 hash of the data contained in this <see cref="AuditEntry"/>. /// </summary> /// <param name="hashAlgorithm"><see cref="SupportedHashAlgorithm"/> to use for hashing data.</param> /// <returns>Hash byte array.</returns> private byte[] HashMessage(SupportedHashAlgorithm hashAlgorithm) { HashAlgorithm hasher = null; switch (hashAlgorithm) { case SupportedHashAlgorithm.SHA1: hasher = new SHA1Managed(); break; case SupportedHashAlgorithm.SHA256: hasher = new SHA256Managed(); break; case SupportedHashAlgorithm.SHA384: hasher = new SHA384Managed(); break; case SupportedHashAlgorithm.SHA512: hasher = new SHA512Managed(); break; } var endoding = new UnicodeEncoding(); var id = BitConverter.GetBytes(Sequence); var createdAt = BitConverter.GetBytes(CreatedAt.ToBinary()); var strData = endoding.GetBytes($"{Stream}{Action}{UserDetails}{DataPayload}"); return(hasher.ComputeHash(id.Concat(createdAt).Concat(strData).ToArray())); }
/// <summary> /// Uses the provided <see cref="RSACryptoServiceProvider"/> to verify the <see cref="Signature"/> /// for this <see cref="AuditEntry"/>. /// </summary> /// <param name="csp"><see cref="RSACryptoServiceProvider"/> that contains a public key to verify this <see cref="AuditEntry"/> with.</param> /// <param name="hashAlgorithm"><see cref="SupportedHashAlgorithm"/> to use for verifying signature.</param> /// <returns>True if the signature is valid, false otherwise.</returns> public bool VerifyAuditMessage(RSACryptoServiceProvider csp, SupportedHashAlgorithm hashAlgorithm) { var hash = HashMessage(hashAlgorithm); Hash = Convert.ToBase64String(hash); return(csp.VerifyHash(hash, CryptoConfig.MapNameToOID(hashAlgorithm.ToString()), Convert.FromBase64String(Signature))); }
public GUIRow(SupportedHashAlgorithm hashAlgorithm, CheckBox checkBox, TextBox textBox, Button copyButton, ProgressBar progressBar, Image hashCheckImage) { this.hashAlgorithm = hashAlgorithm; this.CheckBox = checkBox; this.TextBox = textBox; this.CopyButton = copyButton; this.progressBar = progressBar; this.HashCheckImage = hashCheckImage; }
public static string Hash(string plainText, SupportedHashAlgorithm hashAlgorithm, bool addSalt = true) { // Define min and max salt sizes. const int MinSaltSize = 4; const int MaxSaltSize = 8; return(Hash( plainText, hashAlgorithm, addSalt ? GenerateCryptographicallyRandomBytes(Tools.Maths.RandomNumberGenerator.Next(MinSaltSize, MaxSaltSize)) : null )); }
/// <summary> /// Uses the provided <see cref="RSACryptoServiceProvider"/> to sign this <see cref="AuditEntry"/>. /// </summary> /// <param name="csp"><see cref="RSACryptoServiceProvider"/> that contains a private key to sign this <see cref="AuditEntry"/> with.</param> /// <param name="hashAlgorithm"><see cref="SupportedHashAlgorithm"/> to use for signing data.</param> public void SignAuditMesssage(RSACryptoServiceProvider csp, SupportedHashAlgorithm hashAlgorithm) { if (Signature != null) { throw new InvalidOperationException("Signature already set!"); } var hash = HashMessage(hashAlgorithm); var algorithm = CryptoConfig.MapNameToOID(hashAlgorithm.ToString()); var signature = csp.SignHash(hash, algorithm); Hash = Convert.ToBase64String(hash); Signature = Convert.ToBase64String(signature); }
/// <summary> /// The overridden PrepareForExecute method. /// </summary> public override void PrepareForExecute() { // Assign internal variables. // Create a string builder to be used later. _stringBuilder = new StringBuilder(); // Create a hash algorithm based on the value in the hash algorithm // component property. SupportedHashAlgorithm selectedHashAlgorithm = (SupportedHashAlgorithm)ComponentMetaData.CustomPropertyCollection[_hashAlgorithmPropertyName].Value; String selectedHashAlgorithmName = selectedHashAlgorithm.ToString(); _hashAlgorithm = HashAlgorithm.Create(selectedHashAlgorithmName); base.PrepareForExecute(); }
/// <summary> /// The overridden Validate method. /// </summary> /// <returns></returns> public override DTSValidationStatus Validate() { Boolean pbCancel; // Only one input is allowed. if (ComponentMetaData.InputCollection.Count > 1) { ComponentMetaData.FireError(0, ComponentMetaData.Name, _errorTooManyInputs, null, 0, out pbCancel); return(DTSValidationStatus.VS_ISBROKEN); } // At least one input column must be selected. if (ComponentMetaData.InputCollection[0].InputColumnCollection.Count < 1) { ComponentMetaData.FireError(0, ComponentMetaData.Name, _errorNoInputColumns, null, 0, out pbCancel); return(DTSValidationStatus.VS_ISBROKEN); } // A valid hash Algorithm must be selected. SupportedHashAlgorithm selectedHashAlgorithm = (SupportedHashAlgorithm)ComponentMetaData.CustomPropertyCollection[_hashAlgorithmPropertyName].Value; if (String.IsNullOrEmpty(selectedHashAlgorithm.ToString())) { ComponentMetaData.FireError(0, ComponentMetaData.Name, _errorNoHashAlgorithm, null, 0, out pbCancel); return(DTSValidationStatus.VS_ISBROKEN); } // The built-in check sum column must not be missing. IDTSOutput100 _output = ComponentMetaData.OutputCollection[0]; List <IDTSOutputColumn100> outputColumnList = new List <IDTSOutputColumn100>(); outputColumnList.AddRange ( _output.OutputColumnCollection.Cast <IDTSOutputColumn100>() ); if (!outputColumnList.Exists(outputColumn => outputColumn.Name == _checkSumColumnName)) { ComponentMetaData.FireError(0, ComponentMetaData.Name, _errorMissingChecksumColumn, null, 0, out pbCancel); return(DTSValidationStatus.VS_ISCORRUPT); } return(base.Validate()); }
/// <summary> /// Generates a hash for the given plain text value and returns a /// 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. /// </summary> /// <param name="plainText"> /// Plaintext value to be hashed. The function does not check whether /// this parameter is null. /// </param> /// <param name="hashAlgorithm"> /// The hash algorithm to use. /// </param> /// <param name="saltBytes"> /// Salt bytes. /// </param> /// <returns> /// Hash value formatted as a base64-encoded string. /// </returns> public static string Hash(string plainText, SupportedHashAlgorithm hashAlgorithm, byte[] saltBytes) { if (saltBytes == null) { saltBytes = new byte[0]; } // Convert plain text into a byte array. byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); // Allocate array, which will hold plain text and salt. byte[] plainTextWithSaltBytes = new byte[plainTextBytes.Length + saltBytes.Length]; // Copy plain text bytes into resulting array. for (int i = 0; i < plainTextBytes.Length; i++) { plainTextWithSaltBytes[i] = plainTextBytes[i]; } // Append salt bytes to the resulting array. for (int 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 SupportedHashAlgorithm.SHA1: hash = new SHA1Managed(); break; case SupportedHashAlgorithm.SHA256: hash = new SHA256Managed(); break; #if !__WP8__ case SupportedHashAlgorithm.SHA384: hash = new SHA384Managed(); break; case SupportedHashAlgorithm.SHA512: hash = new SHA512Managed(); break; case SupportedHashAlgorithm.MD5: hash = new MD5CryptoServiceProvider(); break; #endif default: throw new SoftwareException("Failed to compute hash. Requested an unsupported hash algorithm '{0}'", hashAlgorithm); } // Compute hash value of our plain text with appended salt. byte[] hashBytes = hash.ComputeHash(plainTextWithSaltBytes); // Create array which will hold hash and original salt bytes. byte[] hashWithSaltBytes = new byte[hashBytes.Length + saltBytes.Length]; // Copy hash bytes into resulting array. for (int i = 0; i < hashBytes.Length; i++) { hashWithSaltBytes[i] = hashBytes[i]; } // Append salt bytes to the result. for (int i = 0; i < saltBytes.Length; i++) { hashWithSaltBytes[hashBytes.Length + i] = saltBytes[i]; } // Convert result into a base64-encoded string. string hashValue = Convert.ToBase64String(hashWithSaltBytes); // Return the result. return(hashValue); }
/// <summary> /// Creates a hashed representation of the plain text. /// This constructor uses the salt from the <see cref="oldHashedValue" /> in order to make comparison between /// hashed values easier. This should be used with caution and is only recommended in instances such as /// keeping a password history where you want to see if a password has been used before. If the hash has to /// be calculated for each password in the history this could take a large amount of time. /// </summary> /// <param name="plainText">The text to hash</param> /// <param name="oldHashedValue">A hashed value in which to re-use the salt from.</param> /// <param name="saltProvider">Provider of the salt used for creating the hash.</param> private HashedValue(string plainText, HashedValue oldHashedValue) { _algorithm = oldHashedValue.Algorithm; _complexityThrottle = oldHashedValue.ComplexityThrottle; ComputeHashWorker(plainText, _algorithm, _complexityThrottle, oldHashedValue.SaltBytes); }
public IHashedValue CreateHash(string text, SupportedHashAlgorithm algorithm, int hashComplexity) { return(new HashedValue(text, algorithm, hashComplexity, _cryptoProvider)); }
public static IAuditTrailHubBuilder AddMongoDBMerkleTree(this IAuditTrailHubBuilder builder, SupportedHashAlgorithm hashAlgorithm, ECParameters signatureParameters) { Sha2 sha = hashAlgorithm switch { SupportedHashAlgorithm.Sha256 => Sha256.Shared, SupportedHashAlgorithm.Sha384 => Sha384.Shared, SupportedHashAlgorithm.Sha512 => Sha512.Shared, _ => Sha256.Shared }; builder.Services.TryAddSingleton <IMerkleHasher>(new MerkleHasher(sha)); builder.Services.TryAddSingleton <IMerkleSigner>(new ECDsaMerkleSigner(signatureParameters)); builder.Services.Replace(new ServiceDescriptor(typeof(IMerkleTree), typeof(MongoDBMerkleTree), ServiceLifetime.Singleton)); return(builder); } }
public Hash(SupportedHashAlgorithm hashAlgorithm, bool?hmac) { this.HashAlgorithm = hashAlgorithm; this.Hmac = hmac; }
/// <summary> /// Compares a hash of the specified plain text value to a given hash /// value. Plain text is hashed with the same salt value as the original /// hash. /// </summary> /// <param name="plainText"> /// Plain text to be verified against the specified hash. The function /// does not check whether this parameter is null. /// </param> /// <param name="hashAlgorithm"> /// 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. /// </param> /// <param name="hashValue"> /// Base64-encoded hash value produced by ComputeHash function. This value /// includes the original salt appended to it. /// </param> /// <returns> /// If computed hash mathes the specified hash the function the return /// value is true; otherwise, the function returns false. /// </returns> /// <remarks>The salt is retrieved by getting the excess bytes off the end of the hashValue, since each hash algorithm provides fixed length hash.</remarks> public static bool VerifyHash(string plainText, SupportedHashAlgorithm hashAlgorithm, string hashValue) { // Convert base64-encoded hash value into a byte array. byte[] hashWithSaltBytes = Convert.FromBase64String(hashValue); // We must know size of hash (without salt). int hashSizeInBits, hashSizeInBytes; // Size of hash is based on the specified algorithm. switch (hashAlgorithm) { case SupportedHashAlgorithm.SHA1: hashSizeInBits = 160; break; case SupportedHashAlgorithm.SHA256: hashSizeInBits = 256; break; #if !__WP8__ case SupportedHashAlgorithm.SHA384: hashSizeInBits = 384; break; case SupportedHashAlgorithm.SHA512: hashSizeInBits = 512; break; case SupportedHashAlgorithm.MD5: hashSizeInBits = 128; break; #endif default: throw new SoftwareException("Failed to verify hash. Requested an unsupported hash algorithm '{0}'", hashAlgorithm); 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 = Hash(plainText, hashAlgorithm, saltBytes); // If the computed hash matches the specified hash, // the plain text value must be correct. return(hashValue == expectedHashString); }
private void Init() { if (_inited) { return; } _algorithm = DetermineHashTypeFromHash(HashString); byte[] hashWithSaltBytes = Convert.FromBase64String(HashString); int hashSizeInBits; bool hasIterationsCount = false; switch (_algorithm) { case SupportedHashAlgorithm.SHA1: hashSizeInBits = 160; break; case SupportedHashAlgorithm.SHA256: hashSizeInBits = 256; break; case SupportedHashAlgorithm.SHA384: hashSizeInBits = 384; break; case SupportedHashAlgorithm.SHA512: hashSizeInBits = 512; break; case SupportedHashAlgorithm.PBKDF2: hashSizeInBits = 192; hasIterationsCount = true; break; default: hashSizeInBits = 128; break; } var hashSizeInBytes = hashSizeInBits / 8; var iterationCountSizeInBytes = hasIterationsCount ? 4 : 0; var algoMarkerSizeInBytes = _algorithm != SupportedHashAlgorithm.MD5 ? 6 : 0; if (hashWithSaltBytes.Length < (hashSizeInBytes + iterationCountSizeInBytes)) { throw new FormatException("Hash value should have salt but doesnt."); } _saltBytes = new byte[ hashWithSaltBytes.Length - (hashSizeInBytes + iterationCountSizeInBytes + algoMarkerSizeInBytes)]; for (int i = 0; i < _saltBytes.Length; i++) { _saltBytes[i] = hashWithSaltBytes[hashSizeInBytes + i]; } var iterationBytes = new byte[iterationCountSizeInBytes]; for (int i = 0; i < iterationBytes.Length; i++) { iterationBytes[i] = hashWithSaltBytes[hashSizeInBytes + _saltBytes.Length + i]; } _complexityThrottle = hasIterationsCount ? BitConverter.ToInt32(iterationBytes, 0) : 1; _inited = true; }
/// <summary> /// Method for generating password from input values. /// </summary> /// <param name="host"></param> /// <param name="login"></param> /// <param name="passphrase"></param> /// <param name="algorithm"></param> /// <param name="characterSet"></param> /// <param name="maxPwLength"></param> /// <returns>Generated password</returns> public static string GeneratePassword(string host, string login, string passphrase, SupportedHashAlgorithm algorithm, string characterSet, int maxPwLength) { var hashAlgorithm = CryptoConfig.CreateFromName(algorithm.ToString()) as HashAlgorithm; string basestring; if (login.Length == 0) { basestring = passphrase + "@" + host; } else { basestring = login + "@" + host + "#" + passphrase; } byte[] digest = CreateHash(hashAlgorithm, basestring); int digestLength = digest.Length; string sPassword = ""; int pos = 0; int bitno = 0; int charSetLength = characterSet.Length; int maxBitCnt = (int)Math.Ceiling(Math.Log(charSetLength) / Math.Log(2)); for (int i = 0; (i < maxPwLength) && ((pos * 8 + bitno) < (digestLength * 8)); ++i) { int part = 0; int bitCnt = maxBitCnt; int actPos = pos; int actBitno = bitno; for (int j = 0; (j < bitCnt) && ((actPos * 8 + actBitno) < (digestLength * 8)); ++j) { part <<= 1; part |= ((digest[actPos] & (1 << actBitno)) != 0) ? 1 : 0; if (++actBitno >= 8) { ++actPos; actBitno = 0; } } if (part >= charSetLength) { part >>= 1; --actBitno; if (actBitno < 0) { --actPos; actBitno = 7; } } bitno = actBitno; pos = actPos; sPassword = sPassword + characterSet[part]; } return sPassword; }
private void ComputeHashWorker(string plainText, SupportedHashAlgorithm algorithm, int complexityThrottle = 1, byte[] saltBytes = null) { if (saltBytes == null) { saltBytes = _saltProvider.GetNonZeroBytes(SALT_BYTE_LENGTH); } var plainTextBytes = Encoding.UTF8.GetBytes(plainText); var algoBytes = Encoding.UTF8.GetBytes(GetAlgoIdentifier(algorithm)); byte[] hashBytes; var hasComplexityThrottle = false; _complexityThrottle = complexityThrottle; switch (algorithm) { case SupportedHashAlgorithm.SHA1: hashBytes = CryptoHashAlgorithmComputeBytes(plainTextBytes, saltBytes, new SHA1Managed()); break; case SupportedHashAlgorithm.SHA256: hashBytes = CryptoHashAlgorithmComputeBytes(plainTextBytes, saltBytes, new SHA256Managed()); break; case SupportedHashAlgorithm.SHA384: hashBytes = CryptoHashAlgorithmComputeBytes(plainTextBytes, saltBytes, new SHA384Managed()); break; case SupportedHashAlgorithm.SHA512: hashBytes = CryptoHashAlgorithmComputeBytes(plainTextBytes, saltBytes, new SHA512Managed()); break; case SupportedHashAlgorithm.PBKDF2: complexityThrottle = complexityThrottle * 1000; hashBytes = new Rfc2898DeriveBytes(plainTextBytes, saltBytes, complexityThrottle).GetBytes(24); hasComplexityThrottle = true; break; default: hashBytes = CryptoHashAlgorithmComputeBytes(plainTextBytes, saltBytes, new MD5CryptoServiceProvider()); break; } _saltBytes = saltBytes; if (hasComplexityThrottle) { saltBytes = saltBytes.Concat(BitConverter.GetBytes(_complexityThrottle)).ToArray(); } saltBytes = saltBytes.Concat(algoBytes).ToArray(); // append the salt bytes to the end of the hash IEnumerable <byte> hashWithSaltBytes = hashBytes.Concat(saltBytes); HashString = Convert.ToBase64String(hashWithSaltBytes.ToArray()); _inited = true; }
/// <summary> /// Method for generating password from input values. /// </summary> /// <param name="host"></param> /// <param name="login"></param> /// <param name="passphrase"></param> /// <param name="algorithm"></param> /// <param name="characterSet"></param> /// <param name="maxPwLength"></param> /// <returns>Generated password</returns> public static string GeneratePassword(string host, string login, string passphrase, SupportedHashAlgorithm algorithm, string characterSet, int maxPwLength) { var hashAlgorithm = CryptoConfig.CreateFromName(algorithm.ToString()) as HashAlgorithm; var basestring = string.IsNullOrWhiteSpace(login) ? $"{passphrase}@{host}" : $"{login}@{host}#{passphrase}"; var digest = CreateHash(hashAlgorithm, basestring); var digestLength = digest.Length; var sPassword = string.Empty; var pos = 0; var bitno = 0; var charSetLength = characterSet.Length; var maxBitCnt = (int)Math.Ceiling(Math.Log(charSetLength) / Math.Log(2)); for (var i = 0; (i < maxPwLength) && (pos * 8 + bitno < digestLength * 8); ++i) { var part = 0; var bitCnt = maxBitCnt; var actPos = pos; var actBitno = bitno; for (var j = 0; (j < bitCnt) && (actPos * 8 + actBitno < digestLength * 8); ++j) { part <<= 1; part |= (digest[actPos] & (1 << actBitno)) != 0 ? 1 : 0; if (++actBitno >= 8) { ++actPos; actBitno = 0; } } if (part >= charSetLength) { part >>= 1; --actBitno; if (actBitno < 0) { --actPos; actBitno = 7; } } bitno = actBitno; pos = actPos; sPassword = sPassword + characterSet[part]; } return(sPassword); }
public void When_hashing_Then_works(string toHash, string expected, SupportedHashAlgorithm algo) { string actual = CryptographyHelper.Hash.AsString(algo, toHash); Assert.That(actual, Is.EqualTo(expected)); }