Update to version 2.42.1

Some changes
Removed FutureAccesList code as it works only with UWP
This commit is contained in:
Geoffroy BONNEVILLE
2019-07-26 18:28:53 +02:00
parent 85b0e9f321
commit 26e8e5c223
52 changed files with 1373 additions and 506 deletions

View File

@@ -36,20 +36,20 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
if(pwProfile.Length == 0) return PwgError.Success;
PwCharSet pcs = new PwCharSet(pwProfile.CharSet.ToString());
PwGenerator.PrepareCharSet(pcs, pwProfile);
if(!PwGenerator.PrepareCharSet(pcs, pwProfile))
return PwgError.InvalidCharSet;
char[] v = new char[pwProfile.Length];
try
{
for(int i = 0; i < v.Length; ++i)
{
char ch = PwGenerator.GenerateCharacter(pwProfile,
pcs, crsRandomSource);
char ch = PwGenerator.GenerateCharacter(pcs, crsRandomSource);
if(ch == char.MinValue)
return PwgError.TooFewCharacters;
v[i] = ch;
if(pwProfile.NoRepeatingCharacters) pcs.Remove(ch);
}
byte[] pbUtf8 = StrUtil.Utf8.GetBytes(v);

View File

@@ -34,92 +34,61 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
{
psOut = ProtectedString.Empty;
string strPattern = pwProfile.Pattern;
if(string.IsNullOrEmpty(strPattern)) return PwgError.Success;
CharStream cs = new CharStream(strPattern);
LinkedList<char> llGenerated = new LinkedList<char>();
PwCharSet pcsCurrent = new PwCharSet();
PwCharSet pcsCustom = new PwCharSet();
PwCharSet pcsUsed = new PwCharSet();
bool bInCharSetDef = false;
PwCharSet pcs = new PwCharSet();
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)
while(true)
{
pcsCurrent.Clear();
char ch = cs.ReadChar();
if(ch == char.MinValue) break;
bool bGenerateChar = false;
pcs.Clear();
if(ch == '\\')
{
ch = csStream.ReadChar();
if(ch == char.MinValue) // Backslash at the end
{
llGenerated.AddLast('\\');
break;
}
ch = cs.ReadChar();
if(ch == char.MinValue) return PwgError.InvalidPattern;
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);
pcs.Add(ch); // Allow "{...}" support and char check
}
else if(ch == '[')
{
pcsCustom.Clear();
bInCharSetDef = true;
if(!ReadCustomCharSet(cs, pcs))
return PwgError.InvalidPattern;
}
else if(ch == ']')
else
{
pcsCurrent.Add(pcsCustom.ToString());
if(!pcs.AddCharSet(ch))
return PwgError.InvalidPattern;
}
bInCharSetDef = false;
bGenerateChar = true;
}
else if(bInCharSetDef)
int nCount = 1;
if(cs.PeekChar() == '{')
{
if(pcsCustom.AddCharSet(ch) == false)
pcsCustom.Add(ch);
nCount = ReadCount(cs);
if(nCount < 0) return PwgError.InvalidPattern;
}
else if(pcsCurrent.AddCharSet(ch) == false)
{
llGenerated.AddLast(ch);
pcsUsed.Add(ch);
}
else bGenerateChar = true;
if(bGenerateChar)
for(int i = 0; i < nCount; ++i)
{
PwGenerator.PrepareCharSet(pcsCurrent, pwProfile);
if(!PwGenerator.PrepareCharSet(pcs, pwProfile))
return PwgError.InvalidCharSet;
if(pwProfile.NoRepeatingCharacters)
pcsCurrent.Remove(pcsUsed.ToString());
char chGen = PwGenerator.GenerateCharacter(pwProfile,
pcsCurrent, crsRandomSource);
{
foreach(char chUsed in llGenerated)
pcs.Remove(chUsed);
}
char chGen = PwGenerator.GenerateCharacter(pcs,
crsRandomSource);
if(chGen == char.MinValue) return PwgError.TooFewCharacters;
llGenerated.AddLast(chGen);
pcsUsed.Add(chGen);
}
ch = csStream.ReadChar();
}
if(llGenerated.Count == 0) return PwgError.Success;
@@ -135,53 +104,70 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
MemUtil.ZeroByteArray(pbUtf8);
MemUtil.ZeroArray<char>(v);
llGenerated.Clear();
return PwgError.Success;
}
private static string ExpandPattern(string strPattern)
private static bool ReadCustomCharSet(CharStream cs, PwCharSet pcsOut)
{
if(strPattern == null) { Debug.Assert(false); return string.Empty; }
string str = strPattern;
Debug.Assert(cs.PeekChar() != '['); // Consumed already
Debug.Assert(pcsOut.Size == 0);
bool bAdd = true;
while(true)
{
int nOpen = FindFirstUnescapedChar(str, '{');
int nClose = FindFirstUnescapedChar(str, '}');
char ch = cs.ReadChar();
if(ch == char.MinValue) return false;
if(ch == ']') break;
if((nOpen >= 0) && (nOpen < nClose))
if(ch == '\\')
{
string strCount = str.Substring(nOpen + 1, nClose - nOpen - 1);
str = str.Remove(nOpen, nClose - nOpen + 1);
ch = cs.ReadChar();
if(ch == char.MinValue) return false;
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));
}
if(bAdd) pcsOut.Add(ch);
else pcsOut.Remove(ch);
}
else if(ch == '^')
{
if(bAdd) bAdd = false;
else return false; // '^' toggles the mode only once
}
else
{
PwCharSet pcs = new PwCharSet();
if(!pcs.AddCharSet(ch)) return false;
if(bAdd) pcsOut.Add(pcs.ToString());
else pcsOut.Remove(pcs.ToString());
}
else break;
}
return str;
return true;
}
private static int FindFirstUnescapedChar(string str, char ch)
private static int ReadCount(CharStream cs)
{
for(int i = 0; i < str.Length; ++i)
{
char chCur = str[i];
if(cs.ReadChar() != '{') { Debug.Assert(false); return -1; }
if(chCur == '\\') ++i; // Next is escaped, skip it
else if(chCur == ch) return i;
// Ensure not empty
char chFirst = cs.PeekChar();
if((chFirst < '0') || (chFirst > '9')) return -1;
long n = 0;
while(true)
{
char ch = cs.ReadChar();
if(ch == '}') break;
if((ch >= '0') && (ch <= '9'))
{
n = (n * 10L) + (long)(ch - '0');
if(n > int.MaxValue) return -1;
}
else return -1;
}
return -1;
return (int)n;
}
}
}

View File

@@ -43,7 +43,6 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
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;

View File

@@ -36,7 +36,9 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
Success = 0,
Unknown = 1,
TooFewCharacters = 2,
UnknownAlgorithm = 3
UnknownAlgorithm = 3,
InvalidCharSet = 4,
InvalidPattern = 5
}
/// <summary>
@@ -94,30 +96,33 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
return new CryptoRandomStream(CrsAlgorithm.ChaCha20, pbKey);
}
internal static char GenerateCharacter(PwProfile pwProfile,
PwCharSet pwCharSet, CryptoRandomStream crsRandomSource)
internal static char GenerateCharacter(PwCharSet pwCharSet,
CryptoRandomStream crsRandomSource)
{
if(pwCharSet.Size == 0) return char.MinValue;
uint cc = pwCharSet.Size;
if(cc == 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;
uint i = (uint)crsRandomSource.GetRandomUInt64(cc);
return pwCharSet[i];
}
internal static void PrepareCharSet(PwCharSet pwCharSet, PwProfile pwProfile)
internal static bool PrepareCharSet(PwCharSet pwCharSet, PwProfile pwProfile)
{
pwCharSet.Remove(PwCharSet.Invalid);
uint cc = pwCharSet.Size;
for(uint i = 0; i < cc; ++i)
{
char ch = pwCharSet[i];
if((ch == char.MinValue) || (ch == '\t') || (ch == '\r') ||
(ch == '\n') || char.IsSurrogate(ch))
return false;
}
if(pwProfile.ExcludeLookAlike) pwCharSet.Remove(PwCharSet.LookAlike);
if(pwProfile.ExcludeCharacters.Length > 0)
if(!string.IsNullOrEmpty(pwProfile.ExcludeCharacters))
pwCharSet.Remove(pwProfile.ExcludeCharacters);
return true;
}
internal static void Shuffle(char[] v, CryptoRandomStream crsRandomSource)
@@ -127,8 +132,7 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
for(int i = v.Length - 1; i >= 1; --i)
{
ulong r = crsRandomSource.GetRandomUInt64();
int j = (int)(r % (ulong)(i + 1));
int j = (int)crsRandomSource.GetRandomUInt64((ulong)(i + 1));
char t = v[i];
v[i] = v[j];