/// <summary> /// Generates a random secure buffer of bytes /// </summary> public Security.SecureBuffer NextRandomSecureBuffer(int minLength, int maxLength) { if (minLength < 0) { minLength = 0; } var count = minLength; if (maxLength > minLength) { count = this.NextScaledRandomInteger(minLength, maxLength); } var buffer = new Security.SecureBuffer(count); var bytes = new byte[4]; for (var i = 0; i < count; i += 4) { bytes.WriteBEInt32(this.NextRandomInteger); for (var j = 0; j < 4 && i + j < count; j++) { buffer.Push(bytes[j]); bytes[j] = 0; } } buffer.Seal(); return(buffer); }
/// <summary> /// Generates a random secure buffer of chars which are safe for the use on the web - /// a string that only contains "a-z"/"A-Z" and "0-9" and "-"/"_" chars, i.e.: "bo7O0EFasZe-wEty9w0__JiOKk81". /// The length of the string can not be less than 4 and more than 1024 chars /// </summary> public Security.SecureBuffer NextRandomWebSafeSecureBuffer(int minLength = 16, int maxLength = 32) { const int MIN_LEN = 4; const int MAX_LEN = 1024; if (minLength < MIN_LEN) { minLength = MIN_LEN; } if (maxLength > MAX_LEN) { maxLength = MAX_LEN; } var count = minLength; if (maxLength > minLength) { count += this.NextScaledRandomInteger(0, maxLength - minLength); } var result = new Security.SecureBuffer(count); for (var i = 0; i < count; i++) { var b = (byte)CHAR_DICT[(this.NextRandomInteger & CoreConsts.ABS_HASH_MASK) % CHAR_DICT_LEN]; result.Push(b); } result.Seal(); return(result); }
public int CalculateStrenghtPercent(PasswordFamily family, SecureBuffer password, int maxScore = 0) { if (maxScore <= 0) { maxScore = TOP_SCORE_NORMAL; } var score = DoCalculateStrenghtScore(family, password); var result = (int)(100d * (score / (double)maxScore)); return(result > 100 ? 100 : result); }
public int CalculateStrenghtScore(PasswordFamily family, SecureBuffer password) { if (password == null) { throw new SecurityException(StringConsts.ARGUMENT_ERROR + "DefaultPasswordManager.CalculateStrenghtScore(password==null)"); } if (!password.IsSealed) { throw new SecurityException(StringConsts.ARGUMENT_ERROR + "DefaultPasswordManager.CalculateStrenghtScore(!password.IsSealed)"); } CheckServiceActive(); return(DoCalculateStrenghtScore(family, password)); }
public HashedPassword ComputeHash(PasswordFamily family, SecureBuffer password) { if (password == null) { throw new SecurityException(StringConsts.ARGUMENT_ERROR + "PasswordManager.ComputeHash(password==null)"); } if (!password.IsSealed) { throw new SecurityException(StringConsts.ARGUMENT_ERROR + "PasswordManager.ComputeHash(!password.IsSealed)"); } CheckServiceActive(); return(DoComputeHash(family, password)); }
public HashedPassword ComputeHash(PasswordFamily family, SecureBuffer password, PasswordStrengthLevel level = PasswordStrengthLevel.Default) { if (password == null) { throw new SecurityException(StringConsts.ARGUMENT_ERROR + "DefaultPasswordManager.ComputeHash(password==null)"); } if (!password.IsSealed) { throw new SecurityException(StringConsts.ARGUMENT_ERROR + "DefaultPasswordManager.ComputeHash(!password.IsSealed)"); } CheckServiceActive(); return(DoComputeHash(family, password, level == PasswordStrengthLevel.Default ? DefaultStrengthLevel : level)); }
public bool Verify(SecureBuffer password, HashedPassword hash, out bool needRehash) { if (password == null || hash == null) { throw new SecurityException(StringConsts.ARGUMENT_ERROR + "PasswordManager.Verify((password|hash)==null)"); } if (!password.IsSealed) { throw new SecurityException(StringConsts.ARGUMENT_ERROR + "PasswordManager.Verify(!password.IsSealed)"); } needRehash = false; if (!Running) { return(false); } return(DoVerify(password, hash, out needRehash)); }
protected virtual bool DoVerify(SecureBuffer password, HashedPassword hash, out bool needRehash) { needRehash = false; var algo = m_Algorithms[hash.AlgoName]; if (algo == null) { return(false); } bool need = false; if (!algo.Verify(password, hash, out need)) { return(false); } needRehash = !algo.IsDefault || need; return(true); }
protected override HashedPassword DoComputeHash(PasswordFamily family, SecureBuffer password, MD5PasswordHashingOptions options) { using (var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider()) { var content = password.Content; var contentLength = content.Length; var salt = options.Salt; var buffer = new byte[contentLength + salt.Length]; Array.Copy(content, buffer, contentLength); Array.Copy(salt, 0, buffer, contentLength, salt.Length); var hash = md5.ComputeHash(buffer); Array.Clear(buffer, 0, buffer.Length); return(new HashedPassword(Name, family) { { "hash", Convert.ToBase64String(hash) }, { "salt", Convert.ToBase64String(salt) } }); } }
/// <summary> /// Obtains an unsecure string password as SecureBuffer. /// Note: The IDPasswordCredentials class is purposely designed to store password as plain text. /// This is needed for simple cases and HTTP application where login credentials are posted via plain text anyway /// </summary> public static SecureBuffer PlainPasswordToSecureBuffer(string password) { SecureBuffer buffer; if (password.IsNullOrEmpty()) { buffer = new SecureBuffer(0); } else { var bytes = Encoding.UTF8.GetBytes(password); buffer = new SecureBuffer(bytes.Length); foreach (var b in bytes) { buffer.Push(b); } Array.Clear(bytes, 0, bytes.Length); } buffer.Seal(); return(buffer); }
protected virtual HashedPassword DoComputeHash(PasswordFamily family, SecureBuffer password, PasswordStrengthLevel level) { var algoFamily = m_Algorithms.Where(al => al.Match(family)); if (!algoFamily.Any()) { throw new SecurityException(GetType().Name + ".DoComputeHash(family!match)"); } var algs = algoFamily.Where(al => al.StrengthLevel == level); if (!algs.Any()) { algs = algoFamily.Where(al => al.StrengthLevel > level).OrderBy(al => al.StrengthLevel); } if (!algs.Any()) { algs = algoFamily; } var algo = algs.FirstOrDefault(al => al.IsDefault) ?? algs.First(); return(algo.ComputeHash(family, password)); }
protected abstract bool DoVerify(SecureBuffer password, HashedPassword hash, out bool needRehash);
protected abstract HashedPassword DoComputeHash(PasswordFamily family, SecureBuffer password);
protected virtual int DoCalculateStrenghtScore(PasswordFamily family, SecureBuffer password) { var chars = Encoding.UTF8.GetChars(password.Content); if (chars.Length == 0) { return(0); } try { var begin = Array.FindIndex(chars, c => !Char.IsWhiteSpace(c)); if (begin < 0) { return(0); } if (chars.Length == begin) { return(0); } var end = Array.FindLastIndex(chars, c => !Char.IsWhiteSpace(c)) + 1; var score = (end - begin) * CREDIT_CHAR_PRESENT; if (score == 0) { return(0); } var wasUpper = false; var wasLower = false; var wasDigit = false; var wasSymbol = false; char pc = (char)0; for (var i = begin; i < end; i++) { var c = chars[i]; if (Char.IsUpper(c)) { wasUpper = true; } if (Char.IsLower(c)) { wasLower = true; } if (Char.IsDigit(c)) { wasDigit = true; } if (isSymbol(c)) { wasSymbol = true; } if (i > 0 && (Char.IsUpper(c) != Char.IsUpper(pc) || Char.IsDigit(c) != Char.IsDigit(pc) || isSymbol(c) != isSymbol(pc))) { score += CREDIT_TYPE_TRANSITION; } if (c == pc) { score -= DEBIT_CHAR_REPEAT; } if (Math.Abs(c - pc) == 1) { score -= DEBIT_ADJACENT_CHAR; } pc = c; chars[i] = Char.ToLowerInvariant(c); } if (wasUpper && wasLower) { score += CREDIT_CASE_MIX; } if (wasDigit && (wasUpper || wasLower || wasSymbol)) { score += CREDIT_DIGIT_MIX; } if (wasSymbol) { score += CREDIT_SYMBOL_MIX; } for (var i = 0; i < DEFAULT_COMMON_WORDS.Length; i++) { var commonChars = DEFAULT_COMMON_WORDS[i].ToCharArray(); var from = begin; while ((from = Array.IndexOf(chars, commonChars[0], from)) >= 0) { var find = true; var j = 0; for (; j < commonChars.Length && from + j < chars.Length; j++) { if (chars[from + j] != commonChars[j]) { find = false; break; } } if (find && j == commonChars.Length) { score -= DEBIT_COMMON_WORD; } from++; } } return(score < 0 ? 0 : score); } finally { Array.Clear(chars, 0, chars.Length); } }