private string Shuffle(string password, KeccakNumberGenerator rng) { var builder = new StringBuilder(password); for (int i = builder.Length; i > 1; --i) { int swapIndex = rng.NextInt(i); var temp = builder[i - 1]; builder[i - 1] = builder[swapIndex]; builder[swapIndex] = temp; } return(builder.ToString()); }
private string PickUnits(KeccakNumberGenerator rng) { var builder = new StringBuilder(); var remainingCounts = UnitSets.ToDictionary(u => u, u => u.Bounds.Max); // Fill in the minimum amount of each unit set. foreach (var unitSet in UnitSets) { for (int i = 0; i < unitSet.Bounds.Min; ++i) { builder.Append(unitSet[rng.NextInt(unitSet.Count)]); } } // Fill in the rest with random characters from the entire superset, // removing sets if they reach their maximum var availableUnitSets = UnitSets.Where(u => u.Bounds.Max > u.Bounds.Min).ToList(); int supersetCount = availableUnitSets.Sum(u => u.Count); while (builder.Length < Length) { int supersetIndex = rng.NextInt(supersetCount); for (int i = 0; i < availableUnitSets.Count; ++i) { if (supersetIndex < availableUnitSets[i].Count) { builder.Append(availableUnitSets[i][supersetIndex]); --remainingCounts[availableUnitSets[i]]; if (remainingCounts[availableUnitSets[i]] == 0) { availableUnitSets.Remove(availableUnitSets[i]); supersetCount = availableUnitSets.Sum(u => u.Count); } break; } supersetIndex -= availableUnitSets[i].Count; } } return(builder.ToString()); }
public string Generate() { var seedBuilder = new StringBuilder(); AddSeedPart(seedBuilder, MasterPassword); AddSeedPart(seedBuilder, Keyword); AddSeedPart(seedBuilder, Modifier); AddSeedPart(seedBuilder, Length); foreach (var unitSet in UnitSets) { AddSeedPart(seedBuilder, unitSet); } var rng = new KeccakNumberGenerator(seedBuilder.ToString()); string unshuffled = PickUnits(rng); string password = Shuffle(unshuffled, rng); return(password); }