mirror of
https://github.com/wismna/ModernKeePassLib.git
synced 2025-10-03 15:40:20 -04:00
Setup solution
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using ModernKeePassLib.Security;
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography.PasswordGenerator
|
||||
{
|
||||
internal static class CharSetBasedGenerator
|
||||
{
|
||||
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());
|
||||
PwGenerator.PrepareCharSet(pcs, pwProfile);
|
||||
|
||||
char[] v = new char[pwProfile.Length];
|
||||
try
|
||||
{
|
||||
for(int i = 0; i < v.Length; ++i)
|
||||
{
|
||||
char ch = PwGenerator.GenerateCharacter(pwProfile,
|
||||
pcs, crsRandomSource);
|
||||
|
||||
if(ch == char.MinValue)
|
||||
return PwgError.TooFewCharacters;
|
||||
|
||||
v[i] = ch;
|
||||
}
|
||||
|
||||
byte[] pbUtf8 = StrUtil.Utf8.GetBytes(v);
|
||||
psOut = new ProtectedString(true, pbUtf8);
|
||||
MemUtil.ZeroByteArray(pbUtf8);
|
||||
}
|
||||
finally { MemUtil.ZeroArray<char>(v); }
|
||||
|
||||
return PwgError.Success;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using ModernKeePassLib;
|
||||
using ModernKeePassLib.Security;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography.PasswordGenerator
|
||||
{
|
||||
public abstract class CustomPwGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Each custom password generation algorithm must have
|
||||
/// its own unique UUID.
|
||||
/// </summary>
|
||||
public abstract PwUuid Uuid { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Displayable name of the password generation algorithm.
|
||||
/// </summary>
|
||||
public abstract string Name { get; }
|
||||
|
||||
public virtual bool SupportsOptions
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <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);
|
||||
|
||||
public virtual string GetOptions(string strCurrentOptions)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography.PasswordGenerator
|
||||
{
|
||||
public sealed class CustomPwGeneratorPool : IEnumerable<CustomPwGenerator>
|
||||
{
|
||||
private List<CustomPwGenerator> m_vGens = new List<CustomPwGenerator>();
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return m_vGens.Count; }
|
||||
}
|
||||
|
||||
public CustomPwGeneratorPool()
|
||||
{
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return m_vGens.GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<CustomPwGenerator> GetEnumerator()
|
||||
{
|
||||
return m_vGens.GetEnumerator();
|
||||
}
|
||||
|
||||
public void Add(CustomPwGenerator pwg)
|
||||
{
|
||||
if(pwg == null) throw new ArgumentNullException("pwg");
|
||||
|
||||
PwUuid uuid = pwg.Uuid;
|
||||
if(uuid == null) throw new ArgumentException();
|
||||
|
||||
int nIndex = FindIndex(uuid);
|
||||
|
||||
if(nIndex >= 0) m_vGens[nIndex] = pwg; // Replace
|
||||
else m_vGens.Add(pwg);
|
||||
}
|
||||
|
||||
public CustomPwGenerator Find(PwUuid uuid)
|
||||
{
|
||||
if(uuid == null) throw new ArgumentNullException("uuid");
|
||||
|
||||
foreach(CustomPwGenerator pwg in m_vGens)
|
||||
{
|
||||
if(uuid.Equals(pwg.Uuid)) return pwg;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public CustomPwGenerator Find(string strName)
|
||||
{
|
||||
if(strName == null) throw new ArgumentNullException("strName");
|
||||
|
||||
foreach(CustomPwGenerator pwg in m_vGens)
|
||||
{
|
||||
if(pwg.Name == strName) return pwg;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private int FindIndex(PwUuid uuid)
|
||||
{
|
||||
if(uuid == null) throw new ArgumentNullException("uuid");
|
||||
|
||||
for(int i = 0; i < m_vGens.Count; ++i)
|
||||
{
|
||||
if(uuid.Equals(m_vGens[i].Uuid)) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public bool Remove(PwUuid uuid)
|
||||
{
|
||||
if(uuid == null) throw new ArgumentNullException("uuid");
|
||||
|
||||
int nIndex = FindIndex(uuid);
|
||||
if(nIndex < 0) return false;
|
||||
|
||||
m_vGens.RemoveAt(nIndex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using ModernKeePassLib.Security;
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography.PasswordGenerator
|
||||
{
|
||||
internal static class PatternBasedGenerator
|
||||
{
|
||||
internal static PwgError Generate(out ProtectedString psOut,
|
||||
PwProfile pwProfile, CryptoRandomStream crsRandomSource)
|
||||
{
|
||||
psOut = ProtectedString.Empty;
|
||||
|
||||
LinkedList<char> llGenerated = 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
|
||||
{
|
||||
llGenerated.AddLast('\\');
|
||||
break;
|
||||
}
|
||||
|
||||
if(bInCharSetDef) pcsCustom.Add(ch);
|
||||
else
|
||||
{
|
||||
llGenerated.AddLast(ch);
|
||||
pcsUsed.Add(ch);
|
||||
}
|
||||
}
|
||||
else if(ch == '^')
|
||||
{
|
||||
ch = csStream.ReadChar();
|
||||
if(ch == char.MinValue) // ^ at the end
|
||||
{
|
||||
llGenerated.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)
|
||||
{
|
||||
llGenerated.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;
|
||||
|
||||
llGenerated.AddLast(chGen);
|
||||
pcsUsed.Add(chGen);
|
||||
}
|
||||
|
||||
ch = csStream.ReadChar();
|
||||
}
|
||||
|
||||
if(llGenerated.Count == 0) return PwgError.Success;
|
||||
|
||||
char[] v = new char[llGenerated.Count];
|
||||
llGenerated.CopyTo(v, 0);
|
||||
|
||||
if(pwProfile.PatternPermutePassword)
|
||||
PwGenerator.Shuffle(v, crsRandomSource);
|
||||
|
||||
byte[] pbUtf8 = StrUtil.Utf8.GetBytes(v);
|
||||
psOut = new ProtectedString(true, pbUtf8);
|
||||
MemUtil.ZeroByteArray(pbUtf8);
|
||||
|
||||
MemUtil.ZeroArray<char>(v);
|
||||
llGenerated.Clear();
|
||||
|
||||
return PwgError.Success;
|
||||
}
|
||||
|
||||
private static string ExpandPattern(string strPattern)
|
||||
{
|
||||
if(strPattern == null) { Debug.Assert(false); return string.Empty; }
|
||||
|
||||
string str = strPattern;
|
||||
|
||||
while(true)
|
||||
{
|
||||
int nOpen = FindFirstUnescapedChar(str, '{');
|
||||
int nClose = FindFirstUnescapedChar(str, '}');
|
||||
|
||||
if((nOpen >= 0) && (nOpen < nClose))
|
||||
{
|
||||
string strCount = str.Substring(nOpen + 1, nClose - nOpen - 1);
|
||||
str = str.Remove(nOpen, nClose - nOpen + 1);
|
||||
|
||||
uint uRepeat;
|
||||
if(StrUtil.TryParseUInt(strCount, out uRepeat) && (nOpen >= 1))
|
||||
{
|
||||
if(uRepeat == 0)
|
||||
str = str.Remove(nOpen - 1, 1);
|
||||
else
|
||||
str = str.Insert(nOpen, new string(str[nOpen - 1], (int)uRepeat - 1));
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
private static int FindFirstUnescapedChar(string str, char ch)
|
||||
{
|
||||
for(int i = 0; i < str.Length; ++i)
|
||||
{
|
||||
char chCur = str[i];
|
||||
|
||||
if(chCur == '\\') ++i; // Next is escaped, skip it
|
||||
else if(chCur == ch) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
351
ModernKeePassLib/Cryptography/PasswordGenerator/PwCharSet.cs
Normal file
351
ModernKeePassLib/Cryptography/PasswordGenerator/PwCharSet.cs
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography.PasswordGenerator
|
||||
{
|
||||
public sealed class PwCharSet
|
||||
{
|
||||
public static readonly string UpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
public static readonly string LowerCase = "abcdefghijklmnopqrstuvwxyz";
|
||||
public static readonly string Digits = "0123456789";
|
||||
|
||||
public static readonly string UpperConsonants = "BCDFGHJKLMNPQRSTVWXYZ";
|
||||
public static readonly string LowerConsonants = "bcdfghjklmnpqrstvwxyz";
|
||||
public static readonly string UpperVowels = "AEIOU";
|
||||
public static readonly string LowerVowels = "aeiou";
|
||||
|
||||
public static readonly string Punctuation = @",.;:";
|
||||
public static readonly string Brackets = @"[]{}()<>";
|
||||
|
||||
public static readonly string PrintableAsciiSpecial = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
||||
|
||||
public static readonly string UpperHex = "0123456789ABCDEF";
|
||||
public static readonly string LowerHex = "0123456789abcdef";
|
||||
|
||||
public static readonly string Invalid = "\t\r\n";
|
||||
public static readonly string LookAlike = @"O0l1I|";
|
||||
|
||||
internal static readonly string MenuAccels = PwCharSet.LowerCase + PwCharSet.Digits;
|
||||
|
||||
private const int CharTabSize = 0x10000 / 8;
|
||||
|
||||
private List<char> m_vChars = new List<char>();
|
||||
private byte[] m_vTab = new byte[CharTabSize];
|
||||
|
||||
private static string m_strHighAnsi = null;
|
||||
public static string HighAnsiChars
|
||||
{
|
||||
get
|
||||
{
|
||||
if(m_strHighAnsi == null) { new PwCharSet(); } // Create string
|
||||
Debug.Assert(m_strHighAnsi != null);
|
||||
return m_strHighAnsi;
|
||||
}
|
||||
}
|
||||
|
||||
private static string m_strSpecial = null;
|
||||
public static string SpecialChars
|
||||
{
|
||||
get
|
||||
{
|
||||
if(m_strSpecial == null) { new PwCharSet(); } // Create string
|
||||
Debug.Assert(m_strSpecial != null);
|
||||
return m_strSpecial;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new, empty character set collection object.
|
||||
/// </summary>
|
||||
public PwCharSet()
|
||||
{
|
||||
Initialize(true);
|
||||
}
|
||||
|
||||
public PwCharSet(string strCharSet)
|
||||
{
|
||||
Initialize(true);
|
||||
Add(strCharSet);
|
||||
}
|
||||
|
||||
private PwCharSet(bool bFullInitialize)
|
||||
{
|
||||
Initialize(bFullInitialize);
|
||||
}
|
||||
|
||||
private void Initialize(bool bFullInitialize)
|
||||
{
|
||||
Clear();
|
||||
|
||||
if(!bFullInitialize) return;
|
||||
|
||||
if(m_strHighAnsi == null)
|
||||
{
|
||||
StringBuilder sbHighAnsi = new StringBuilder();
|
||||
// [U+0080, U+009F] are C1 control characters,
|
||||
// U+00A0 is non-breaking space
|
||||
for(char ch = '\u00A1'; ch <= '\u00AC'; ++ch)
|
||||
sbHighAnsi.Append(ch);
|
||||
// U+00AD is soft hyphen (format character)
|
||||
for(char ch = '\u00AE'; ch < '\u00FF'; ++ch)
|
||||
sbHighAnsi.Append(ch);
|
||||
sbHighAnsi.Append('\u00FF');
|
||||
|
||||
m_strHighAnsi = sbHighAnsi.ToString();
|
||||
}
|
||||
|
||||
if(m_strSpecial == null)
|
||||
{
|
||||
PwCharSet pcs = new PwCharSet(false);
|
||||
pcs.AddRange('!', '/');
|
||||
pcs.AddRange(':', '@');
|
||||
pcs.AddRange('[', '`');
|
||||
pcs.Add(@"|~");
|
||||
pcs.Remove(@"-_ ");
|
||||
pcs.Remove(PwCharSet.Brackets);
|
||||
|
||||
m_strSpecial = pcs.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of characters in this set.
|
||||
/// </summary>
|
||||
public uint Size
|
||||
{
|
||||
get { return (uint)m_vChars.Count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a character of the set using an index.
|
||||
/// </summary>
|
||||
/// <param name="uPos">Index of the character to get.</param>
|
||||
/// <returns>Character at the specified position. If the index is invalid,
|
||||
/// an <c>ArgumentOutOfRangeException</c> is thrown.</returns>
|
||||
public char this[uint uPos]
|
||||
{
|
||||
get
|
||||
{
|
||||
if(uPos >= (uint)m_vChars.Count)
|
||||
throw new ArgumentOutOfRangeException("uPos");
|
||||
|
||||
return m_vChars[(int)uPos];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove all characters from this set.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
m_vChars.Clear();
|
||||
Array.Clear(m_vTab, 0, m_vTab.Length);
|
||||
}
|
||||
|
||||
public bool Contains(char ch)
|
||||
{
|
||||
return (((m_vTab[ch / 8] >> (ch % 8)) & 1) != char.MinValue);
|
||||
}
|
||||
|
||||
public bool Contains(string strCharacters)
|
||||
{
|
||||
Debug.Assert(strCharacters != null);
|
||||
if(strCharacters == null) throw new ArgumentNullException("strCharacters");
|
||||
|
||||
foreach(char ch in strCharacters)
|
||||
{
|
||||
if(!Contains(ch)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add characters to the set.
|
||||
/// </summary>
|
||||
/// <param name="ch">Character to add.</param>
|
||||
public void Add(char ch)
|
||||
{
|
||||
if(ch == char.MinValue) { Debug.Assert(false); return; }
|
||||
|
||||
if(!Contains(ch))
|
||||
{
|
||||
m_vChars.Add(ch);
|
||||
m_vTab[ch / 8] |= (byte)(1 << (ch % 8));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add characters to the set.
|
||||
/// </summary>
|
||||
/// <param name="strCharSet">String containing characters to add.</param>
|
||||
public void Add(string strCharSet)
|
||||
{
|
||||
Debug.Assert(strCharSet != null);
|
||||
if(strCharSet == null) throw new ArgumentNullException("strCharSet");
|
||||
|
||||
m_vChars.Capacity = m_vChars.Count + strCharSet.Length;
|
||||
|
||||
foreach(char ch in strCharSet)
|
||||
Add(ch);
|
||||
}
|
||||
|
||||
public void Add(string strCharSet1, string strCharSet2)
|
||||
{
|
||||
Add(strCharSet1);
|
||||
Add(strCharSet2);
|
||||
}
|
||||
|
||||
public void Add(string strCharSet1, string strCharSet2, string strCharSet3)
|
||||
{
|
||||
Add(strCharSet1);
|
||||
Add(strCharSet2);
|
||||
Add(strCharSet3);
|
||||
}
|
||||
|
||||
public void AddRange(char chMin, char chMax)
|
||||
{
|
||||
m_vChars.Capacity = m_vChars.Count + (chMax - chMin) + 1;
|
||||
|
||||
for(char ch = chMin; ch < chMax; ++ch)
|
||||
Add(ch);
|
||||
|
||||
Add(chMax);
|
||||
}
|
||||
|
||||
public bool AddCharSet(char chCharSetIdentifier)
|
||||
{
|
||||
bool bResult = true;
|
||||
|
||||
switch(chCharSetIdentifier)
|
||||
{
|
||||
case 'a': Add(PwCharSet.LowerCase, PwCharSet.Digits); break;
|
||||
case 'A': Add(PwCharSet.LowerCase, PwCharSet.UpperCase,
|
||||
PwCharSet.Digits); break;
|
||||
case 'U': Add(PwCharSet.UpperCase, PwCharSet.Digits); break;
|
||||
case 'c': Add(PwCharSet.LowerConsonants); break;
|
||||
case 'C': Add(PwCharSet.LowerConsonants,
|
||||
PwCharSet.UpperConsonants); break;
|
||||
case 'z': Add(PwCharSet.UpperConsonants); break;
|
||||
case 'd': Add(PwCharSet.Digits); break; // Digit
|
||||
case 'h': Add(PwCharSet.LowerHex); break;
|
||||
case 'H': Add(PwCharSet.UpperHex); break;
|
||||
case 'l': Add(PwCharSet.LowerCase); break;
|
||||
case 'L': Add(PwCharSet.LowerCase, PwCharSet.UpperCase); break;
|
||||
case 'u': Add(PwCharSet.UpperCase); break;
|
||||
case 'p': Add(PwCharSet.Punctuation); break;
|
||||
case 'b': Add(PwCharSet.Brackets); break;
|
||||
case 's': Add(PwCharSet.PrintableAsciiSpecial); break;
|
||||
case 'S': Add(PwCharSet.UpperCase, PwCharSet.LowerCase);
|
||||
Add(PwCharSet.Digits, PwCharSet.PrintableAsciiSpecial); break;
|
||||
case 'v': Add(PwCharSet.LowerVowels); break;
|
||||
case 'V': Add(PwCharSet.LowerVowels, PwCharSet.UpperVowels); break;
|
||||
case 'Z': Add(PwCharSet.UpperVowels); break;
|
||||
case 'x': Add(m_strHighAnsi); break;
|
||||
default: bResult = false; break;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
public bool Remove(char ch)
|
||||
{
|
||||
m_vTab[ch / 8] &= (byte)(~(1 << (ch % 8)));
|
||||
return m_vChars.Remove(ch);
|
||||
}
|
||||
|
||||
public bool Remove(string strCharacters)
|
||||
{
|
||||
Debug.Assert(strCharacters != null);
|
||||
if(strCharacters == null) throw new ArgumentNullException("strCharacters");
|
||||
|
||||
bool bResult = true;
|
||||
foreach(char ch in strCharacters)
|
||||
{
|
||||
if(!Remove(ch)) bResult = false;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
public bool RemoveIfAllExist(string strCharacters)
|
||||
{
|
||||
Debug.Assert(strCharacters != null);
|
||||
if(strCharacters == null) throw new ArgumentNullException("strCharacters");
|
||||
|
||||
if(!Contains(strCharacters))
|
||||
return false;
|
||||
|
||||
return Remove(strCharacters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the character set to a string containing all its characters.
|
||||
/// </summary>
|
||||
/// <returns>String containing all character set characters.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach(char ch in m_vChars)
|
||||
sb.Append(ch);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string PackAndRemoveCharRanges()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.UpperCase) ? 'U' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.LowerCase) ? 'L' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.Digits) ? 'D' : '_');
|
||||
sb.Append(RemoveIfAllExist(m_strSpecial) ? 'S' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.Punctuation) ? 'P' : '_');
|
||||
sb.Append(RemoveIfAllExist(@"-") ? 'm' : '_');
|
||||
sb.Append(RemoveIfAllExist(@"_") ? 'u' : '_');
|
||||
sb.Append(RemoveIfAllExist(@" ") ? 's' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.Brackets) ? 'B' : '_');
|
||||
sb.Append(RemoveIfAllExist(m_strHighAnsi) ? 'H' : '_');
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public void UnpackCharRanges(string strRanges)
|
||||
{
|
||||
if(strRanges == null) { Debug.Assert(false); return; }
|
||||
if(strRanges.Length < 10) { Debug.Assert(false); return; }
|
||||
|
||||
if(strRanges[0] != '_') Add(PwCharSet.UpperCase);
|
||||
if(strRanges[1] != '_') Add(PwCharSet.LowerCase);
|
||||
if(strRanges[2] != '_') Add(PwCharSet.Digits);
|
||||
if(strRanges[3] != '_') Add(m_strSpecial);
|
||||
if(strRanges[4] != '_') Add(PwCharSet.Punctuation);
|
||||
if(strRanges[5] != '_') Add('-');
|
||||
if(strRanges[6] != '_') Add('_');
|
||||
if(strRanges[7] != '_') Add(' ');
|
||||
if(strRanges[8] != '_') Add(PwCharSet.Brackets);
|
||||
if(strRanges[9] != '_') Add(m_strHighAnsi);
|
||||
}
|
||||
}
|
||||
}
|
163
ModernKeePassLib/Cryptography/PasswordGenerator/PwGenerator.cs
Normal file
163
ModernKeePassLib/Cryptography/PasswordGenerator/PwGenerator.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
#if !KeePassUAP
|
||||
using System.Security.Cryptography;
|
||||
#endif
|
||||
|
||||
using ModernKeePassLib.Security;
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography.PasswordGenerator
|
||||
{
|
||||
public enum PwgError
|
||||
{
|
||||
Success = 0,
|
||||
Unknown = 1,
|
||||
TooFewCharacters = 2,
|
||||
UnknownAlgorithm = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Utility functions for generating random passwords.
|
||||
/// </summary>
|
||||
public static class PwGenerator
|
||||
{
|
||||
public static PwgError Generate(out ProtectedString psOut,
|
||||
PwProfile pwProfile, byte[] pbUserEntropy,
|
||||
CustomPwGeneratorPool pwAlgorithmPool)
|
||||
{
|
||||
Debug.Assert(pwProfile != null);
|
||||
if(pwProfile == null) throw new ArgumentNullException("pwProfile");
|
||||
|
||||
PwgError e = PwgError.Unknown;
|
||||
CryptoRandomStream crs = null;
|
||||
byte[] pbKey = null;
|
||||
try
|
||||
{
|
||||
crs = CreateRandomStream(pbUserEntropy, out pbKey);
|
||||
|
||||
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; }
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(crs != null) crs.Dispose();
|
||||
if(pbKey != null) MemUtil.ZeroByteArray(pbKey);
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
private static CryptoRandomStream CreateRandomStream(byte[] pbAdditionalEntropy,
|
||||
out byte[] pbKey)
|
||||
{
|
||||
pbKey = CryptoRandom.Instance.GetRandomBytes(128);
|
||||
|
||||
// Mix in additional entropy
|
||||
Debug.Assert(pbKey.Length >= 64);
|
||||
if((pbAdditionalEntropy != null) && (pbAdditionalEntropy.Length > 0))
|
||||
{
|
||||
using(SHA512Managed h = new SHA512Managed())
|
||||
{
|
||||
byte[] pbHash = h.ComputeHash(pbAdditionalEntropy);
|
||||
MemUtil.XorArray(pbHash, 0, pbKey, 0, pbHash.Length);
|
||||
}
|
||||
}
|
||||
|
||||
return new CryptoRandomStream(CrsAlgorithm.ChaCha20, pbKey);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 void Shuffle(char[] v, CryptoRandomStream crsRandomSource)
|
||||
{
|
||||
if(v == null) { Debug.Assert(false); return; }
|
||||
if(crsRandomSource == null) { Debug.Assert(false); return; }
|
||||
|
||||
for(int i = v.Length - 1; i >= 1; --i)
|
||||
{
|
||||
ulong r = crsRandomSource.GetRandomUInt64();
|
||||
int j = (int)(r % (ulong)(i + 1));
|
||||
|
||||
char t = v[i];
|
||||
v[i] = v[j];
|
||||
v[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
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)) 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;
|
||||
}
|
||||
}
|
||||
}
|
276
ModernKeePassLib/Cryptography/PasswordGenerator/PwProfile.cs
Normal file
276
ModernKeePassLib/Cryptography/PasswordGenerator/PwProfile.cs
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
|
||||
using ModernKeePassLib.Interfaces;
|
||||
using ModernKeePassLib.Security;
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography.PasswordGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of the password generator. Different types like generators
|
||||
/// based on given patterns, based on character sets, etc. are
|
||||
/// available.
|
||||
/// </summary>
|
||||
public enum PasswordGeneratorType
|
||||
{
|
||||
/// <summary>
|
||||
/// Generator based on character spaces/sets, i.e. groups
|
||||
/// of characters like lower-case, upper-case or numeric characters.
|
||||
/// </summary>
|
||||
CharSet = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Password generation based on a pattern. The user has provided
|
||||
/// a pattern, which describes how the generated password has to
|
||||
/// look like.
|
||||
/// </summary>
|
||||
Pattern = 1,
|
||||
|
||||
Custom = 2
|
||||
}
|
||||
|
||||
public sealed class PwProfile : IDeepCloneable<PwProfile>
|
||||
{
|
||||
private string m_strName = string.Empty;
|
||||
[DefaultValue("")]
|
||||
public string Name
|
||||
{
|
||||
get { return m_strName; }
|
||||
set { m_strName = value; }
|
||||
}
|
||||
|
||||
private PasswordGeneratorType m_type = PasswordGeneratorType.CharSet;
|
||||
public PasswordGeneratorType GeneratorType
|
||||
{
|
||||
get { return m_type; }
|
||||
set { m_type = value; }
|
||||
}
|
||||
|
||||
private bool m_bUserEntropy = false;
|
||||
[DefaultValue(false)]
|
||||
public bool CollectUserEntropy
|
||||
{
|
||||
get { return m_bUserEntropy; }
|
||||
set { m_bUserEntropy = value; }
|
||||
}
|
||||
|
||||
private uint m_uLength = 20;
|
||||
public uint Length
|
||||
{
|
||||
get { return m_uLength; }
|
||||
set { m_uLength = value; }
|
||||
}
|
||||
|
||||
private PwCharSet m_pwCharSet = new PwCharSet(PwCharSet.UpperCase +
|
||||
PwCharSet.LowerCase + PwCharSet.Digits);
|
||||
[XmlIgnore]
|
||||
public PwCharSet CharSet
|
||||
{
|
||||
get { return m_pwCharSet; }
|
||||
set
|
||||
{
|
||||
if(value == null) throw new ArgumentNullException("value");
|
||||
m_pwCharSet = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string m_strCharSetRanges = string.Empty;
|
||||
[DefaultValue("")]
|
||||
public string CharSetRanges
|
||||
{
|
||||
get { this.UpdateCharSet(true); return m_strCharSetRanges; }
|
||||
set
|
||||
{
|
||||
if(value == null) throw new ArgumentNullException("value");
|
||||
m_strCharSetRanges = value;
|
||||
this.UpdateCharSet(false);
|
||||
}
|
||||
}
|
||||
|
||||
private string m_strCharSetAdditional = string.Empty;
|
||||
[DefaultValue("")]
|
||||
public string CharSetAdditional
|
||||
{
|
||||
get { this.UpdateCharSet(true); return m_strCharSetAdditional; }
|
||||
set
|
||||
{
|
||||
if(value == null) throw new ArgumentNullException("value");
|
||||
m_strCharSetAdditional = value;
|
||||
this.UpdateCharSet(false);
|
||||
}
|
||||
}
|
||||
|
||||
private string m_strPattern = string.Empty;
|
||||
[DefaultValue("")]
|
||||
public string Pattern
|
||||
{
|
||||
get { return m_strPattern; }
|
||||
set { m_strPattern = value; }
|
||||
}
|
||||
|
||||
private bool m_bPatternPermute = false;
|
||||
[DefaultValue(false)]
|
||||
public bool PatternPermutePassword
|
||||
{
|
||||
get { return m_bPatternPermute; }
|
||||
set { m_bPatternPermute = value; }
|
||||
}
|
||||
|
||||
private bool m_bNoLookAlike = false;
|
||||
[DefaultValue(false)]
|
||||
public bool ExcludeLookAlike
|
||||
{
|
||||
get { return m_bNoLookAlike; }
|
||||
set { m_bNoLookAlike = value; }
|
||||
}
|
||||
|
||||
private bool m_bNoRepeat = false;
|
||||
[DefaultValue(false)]
|
||||
public bool NoRepeatingCharacters
|
||||
{
|
||||
get { return m_bNoRepeat; }
|
||||
set { m_bNoRepeat = value; }
|
||||
}
|
||||
|
||||
private string m_strExclude = string.Empty;
|
||||
[DefaultValue("")]
|
||||
public string ExcludeCharacters
|
||||
{
|
||||
get { return m_strExclude; }
|
||||
set
|
||||
{
|
||||
if(value == null) throw new ArgumentNullException("value");
|
||||
m_strExclude = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string m_strCustomID = string.Empty;
|
||||
[DefaultValue("")]
|
||||
public string CustomAlgorithmUuid
|
||||
{
|
||||
get { return m_strCustomID; }
|
||||
set
|
||||
{
|
||||
if(value == null) throw new ArgumentNullException("value");
|
||||
m_strCustomID = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string m_strCustomOpt = string.Empty;
|
||||
[DefaultValue("")]
|
||||
public string CustomAlgorithmOptions
|
||||
{
|
||||
get { return m_strCustomOpt; }
|
||||
set
|
||||
{
|
||||
if(value == null) throw new ArgumentNullException("value");
|
||||
m_strCustomOpt = value;
|
||||
}
|
||||
}
|
||||
|
||||
public PwProfile()
|
||||
{
|
||||
}
|
||||
|
||||
public PwProfile CloneDeep()
|
||||
{
|
||||
PwProfile p = new PwProfile();
|
||||
|
||||
p.m_strName = m_strName;
|
||||
p.m_type = m_type;
|
||||
p.m_bUserEntropy = m_bUserEntropy;
|
||||
p.m_uLength = m_uLength;
|
||||
p.m_pwCharSet = new PwCharSet(m_pwCharSet.ToString());
|
||||
p.m_strCharSetRanges = m_strCharSetRanges;
|
||||
p.m_strCharSetAdditional = m_strCharSetAdditional;
|
||||
p.m_strPattern = m_strPattern;
|
||||
p.m_bPatternPermute = m_bPatternPermute;
|
||||
p.m_bNoLookAlike = m_bNoLookAlike;
|
||||
p.m_bNoRepeat = m_bNoRepeat;
|
||||
p.m_strExclude = m_strExclude;
|
||||
p.m_strCustomID = m_strCustomID;
|
||||
p.m_strCustomOpt = m_strCustomOpt;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private void UpdateCharSet(bool bSetXml)
|
||||
{
|
||||
if(bSetXml)
|
||||
{
|
||||
PwCharSet pcs = new PwCharSet(m_pwCharSet.ToString());
|
||||
m_strCharSetRanges = pcs.PackAndRemoveCharRanges();
|
||||
m_strCharSetAdditional = pcs.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
PwCharSet pcs = new PwCharSet(m_strCharSetAdditional);
|
||||
pcs.UnpackCharRanges(m_strCharSetRanges);
|
||||
m_pwCharSet = pcs;
|
||||
}
|
||||
}
|
||||
|
||||
public static PwProfile DeriveFromPassword(ProtectedString psPassword)
|
||||
{
|
||||
PwProfile pp = new PwProfile();
|
||||
Debug.Assert(psPassword != null); if(psPassword == null) return pp;
|
||||
|
||||
char[] vChars = psPassword.ReadChars();
|
||||
|
||||
pp.GeneratorType = PasswordGeneratorType.CharSet;
|
||||
pp.Length = (uint)vChars.Length;
|
||||
|
||||
PwCharSet pcs = pp.CharSet;
|
||||
pcs.Clear();
|
||||
|
||||
foreach(char ch in vChars)
|
||||
{
|
||||
if((ch >= 'A') && (ch <= 'Z')) pcs.Add(PwCharSet.UpperCase);
|
||||
else if((ch >= 'a') && (ch <= 'z')) pcs.Add(PwCharSet.LowerCase);
|
||||
else if((ch >= '0') && (ch <= '9')) pcs.Add(PwCharSet.Digits);
|
||||
else if(PwCharSet.SpecialChars.IndexOf(ch) >= 0)
|
||||
pcs.Add(PwCharSet.SpecialChars);
|
||||
else if(ch == ' ') pcs.Add(' ');
|
||||
else if(ch == '-') pcs.Add('-');
|
||||
else if(ch == '_') pcs.Add('_');
|
||||
else if(PwCharSet.Brackets.IndexOf(ch) >= 0)
|
||||
pcs.Add(PwCharSet.Brackets);
|
||||
else if(PwCharSet.HighAnsiChars.IndexOf(ch) >= 0)
|
||||
pcs.Add(PwCharSet.HighAnsiChars);
|
||||
else pcs.Add(ch);
|
||||
}
|
||||
|
||||
MemUtil.ZeroArray<char>(vChars);
|
||||
return pp;
|
||||
}
|
||||
|
||||
public bool HasSecurityReducingOption()
|
||||
{
|
||||
return (m_bNoLookAlike || m_bNoRepeat || (m_strExclude.Length > 0));
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user