public static PwgError Generate(out ProtectedString psOut, PwProfile pwProfile, byte[] pbUserEntropy, CustomPwGeneratorPool pwAlgorithmPool) { Debug.Assert(pwProfile != null); if (pwProfile == null) { throw new ArgumentNullException("pwProfile"); } CryptoRandomStream crs = CreateCryptoStream(pbUserEntropy); PwgError e = PwgError.Unknown; if (pwProfile.GeneratorType == PasswordGeneratorType.CharSet) { e = CharSetBasedGenerator.Generate(out psOut, pwProfile, crs); } else if (pwProfile.GeneratorType == PasswordGeneratorType.Pattern) { e = PatternBasedGenerator.Generate(out psOut, pwProfile, crs); } else if (pwProfile.GeneratorType == PasswordGeneratorType.Custom) { e = GenerateCustom(out psOut, pwProfile, crs, pwAlgorithmPool); } else { Debug.Assert(false); psOut = ProtectedString.Empty; } return(e); }
internal static void PrepareCharSet(PwCharSet pwCharSet, PwProfile pwProfile) { pwCharSet.Remove(PwCharSet.Invalid); if (pwProfile.ExcludeLookAlike) { pwCharSet.Remove(PwCharSet.LookAlike); } if (pwProfile.ExcludeCharacters.Length > 0) { pwCharSet.Remove(pwProfile.ExcludeCharacters); } }
internal static char GenerateCharacter(PwProfile pwProfile, PwCharSet pwCharSet, CryptoRandomStream crsRandomSource) { if (pwCharSet.Size == 0) { return(char.MinValue); } ulong uIndex = crsRandomSource.GetRandomUInt64(); uIndex %= (ulong)pwCharSet.Size; char ch = pwCharSet[(uint)uIndex]; if (pwProfile.NoRepeatingCharacters) { pwCharSet.Remove(ch); } return(ch); }
private static PwgError GenerateCustom(out ProtectedString psOut, PwProfile pwProfile, CryptoRandomStream crs, CustomPwGeneratorPool pwAlgorithmPool) { psOut = ProtectedString.Empty; Debug.Assert(pwProfile.GeneratorType == PasswordGeneratorType.Custom); if (pwAlgorithmPool == null) { return(PwgError.UnknownAlgorithm); } string strID = pwProfile.CustomAlgorithmUuid; if (string.IsNullOrEmpty(strID)) { Debug.Assert(false); return(PwgError.UnknownAlgorithm); } byte[] pbUuid = Convert.FromBase64String(strID); PwUuid uuid = new PwUuid(pbUuid); CustomPwGenerator pwg = pwAlgorithmPool.Find(uuid); if (pwg == null) { Debug.Assert(false); return(PwgError.UnknownAlgorithm); } ProtectedString pwd = pwg.Generate(pwProfile.CloneDeep(), crs); if (pwd == null) { return(PwgError.Unknown); } psOut = pwd; return(PwgError.Success); }
internal static PwgError Generate(out ProtectedString psOut, PwProfile pwProfile, CryptoRandomStream crsRandomSource) { psOut = ProtectedString.Empty; if (pwProfile.Length == 0) { return(PwgError.Success); } PwCharSet pcs = new PwCharSet(pwProfile.CharSet.ToString()); char[] vGenerated = new char[pwProfile.Length]; PwGenerator.PrepareCharSet(pcs, pwProfile); for (int nIndex = 0; nIndex < (int)pwProfile.Length; ++nIndex) { char ch = PwGenerator.GenerateCharacter(pwProfile, pcs, crsRandomSource); if (ch == char.MinValue) { Array.Clear(vGenerated, 0, vGenerated.Length); return(PwgError.TooFewCharacters); } vGenerated[nIndex] = ch; } byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vGenerated); psOut = new ProtectedString(true, pbUtf8); MemUtil.ZeroByteArray(pbUtf8); Array.Clear(vGenerated, 0, vGenerated.Length); return(PwgError.Success); }
/// <summary> /// Password generation function. /// </summary> /// <param name="prf">Password generation options chosen /// by the user. This may be <c>null</c>, if the default /// options should be used.</param> /// <param name="crsRandomSource">Source that the algorithm /// can use to generate random numbers.</param> /// <returns>Generated password or <c>null</c> in case /// of failure. If returning <c>null</c>, the caller assumes /// that an error message has already been shown to the user.</returns> public abstract ProtectedString Generate(PwProfile prf, CryptoRandomStream crsRandomSource);
internal static PwgError Generate(out ProtectedString psOut, PwProfile pwProfile, CryptoRandomStream crsRandomSource) { psOut = ProtectedString.Empty; LinkedList <char> vGenerated = new LinkedList <char>(); PwCharSet pcsCurrent = new PwCharSet(); PwCharSet pcsCustom = new PwCharSet(); PwCharSet pcsUsed = new PwCharSet(); bool bInCharSetDef = false; string strPattern = ExpandPattern(pwProfile.Pattern); if (strPattern.Length == 0) { return(PwgError.Success); } CharStream csStream = new CharStream(strPattern); char ch = csStream.ReadChar(); while (ch != char.MinValue) { pcsCurrent.Clear(); bool bGenerateChar = false; if (ch == '\\') { ch = csStream.ReadChar(); if (ch == char.MinValue) // Backslash at the end { vGenerated.AddLast('\\'); break; } if (bInCharSetDef) { pcsCustom.Add(ch); } else { vGenerated.AddLast(ch); pcsUsed.Add(ch); } } else if (ch == '^') { ch = csStream.ReadChar(); if (ch == char.MinValue) // ^ at the end { vGenerated.AddLast('^'); break; } if (bInCharSetDef) { pcsCustom.Remove(ch); } } else if (ch == '[') { pcsCustom.Clear(); bInCharSetDef = true; } else if (ch == ']') { pcsCurrent.Add(pcsCustom.ToString()); bInCharSetDef = false; bGenerateChar = true; } else if (bInCharSetDef) { if (pcsCustom.AddCharSet(ch) == false) { pcsCustom.Add(ch); } } else if (pcsCurrent.AddCharSet(ch) == false) { vGenerated.AddLast(ch); pcsUsed.Add(ch); } else { bGenerateChar = true; } if (bGenerateChar) { PwGenerator.PrepareCharSet(pcsCurrent, pwProfile); if (pwProfile.NoRepeatingCharacters) { pcsCurrent.Remove(pcsUsed.ToString()); } char chGen = PwGenerator.GenerateCharacter(pwProfile, pcsCurrent, crsRandomSource); if (chGen == char.MinValue) { return(PwgError.TooFewCharacters); } vGenerated.AddLast(chGen); pcsUsed.Add(chGen); } ch = csStream.ReadChar(); } if (vGenerated.Count == 0) { return(PwgError.Success); } char[] vArray = new char[vGenerated.Count]; vGenerated.CopyTo(vArray, 0); if (pwProfile.PatternPermutePassword) { PwGenerator.ShufflePassword(vArray, crsRandomSource); } byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vArray); psOut = new ProtectedString(true, pbUtf8); MemUtil.ZeroByteArray(pbUtf8); Array.Clear(vArray, 0, vArray.Length); vGenerated.Clear(); return(PwgError.Success); }