/// <summary> /// This method will compute a hash of a password and salt combination. As a result it does need to take the secure string and read /// through its contents to compute the hash, this is probably the only time the secure string is not secure, other than when its /// created in the first place. /// </summary> /// <param name="password">The password that is to be hashed.</param> /// <param name="salt">The salt to hash with the password so that the password hash is more secure</param> /// <exception cref="ArgumentException">Thrown if the password is empty or null or if the salt is not initialised</exception> /// <returns>A string representing that password and salt, this string can be passed around and persisted wtihout fear of revealing the password</returns> public static string ComputeSaltedHash(SecureString password, PasswordSalt salt) { #region entry checking // TODO b.Assert(password != null, "The password SecureString can not be null when given to SaltyPassword::ComputeSaltedHash"); // TODO Bilge.Assert((salt.IntegerSalt != 0), "When calling SaltyPassword::ComputeSaltedHash All of the salt bytes are zero.", "This is not valid salt, call SaltyPassword.Salt.FillWithSalt()"); if ((password == null) || (password.Length == 0)) { throw new ArgumentException("The password supplied was not valid."); } if (salt.IntegerSalt == 0) { throw new ArgumentException("The salt supplied is not valid."); } #endregion // Create Byte array of password string ASCIIEncoding encoder = new ASCIIEncoding(); Byte[] passwordAndSaltCombo = new byte[password.Length + 4]; passwordAndSaltCombo[0] = salt.Byte1; passwordAndSaltCombo[1] = salt.Byte2; passwordAndSaltCombo[2] = salt.Byte3; passwordAndSaltCombo[3] = salt.Byte4; // Now we take the bytes from the secure string and place them into a byte array so that we can // perform the hash on them. This probably moves them out of secure encrypted memory negating the // whole secure string thing. IntPtr ptr = Marshal.SecureStringToBSTR(password); try { for (int i = 0; i < password.Length; i++) { // this so must break unicode. passwordAndSaltCombo[i + 4] = Marshal.ReadByte(ptr, i * sizeof(char)); } } finally { // Free and Zero the temp we have been using. Marshal.ZeroFreeBSTR(ptr); } //return the calculated hash. string resultingHash; if (HashesAreB64Encoded) { resultingHash = Convert.ToBase64String(SHA1.Create().ComputeHash(passwordAndSaltCombo)); } else { resultingHash = encoder.GetString(SHA1.Create().ComputeHash(passwordAndSaltCombo)); } return(resultingHash); }
private SaltyPassword() { this.Password = new SecureString(); this.Salt = new PasswordSalt(); }
public SaltyPassword(SecureString password, PasswordSalt pws) { this.Password = password; this.Salt.IntegerSalt = pws.IntegerSalt; }