mirror of
https://github.com/wismna/ModernKeePass.git
synced 2025-10-04 08:00:16 -04:00
KeePassLib finally portable (but version 2.19)
Windows Store project stub
This commit is contained in:
157
ModernKeePassLib/Cryptography/Cipher/CipherPool.cs
Normal file
157
ModernKeePassLib/Cryptography/Cipher/CipherPool.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography.Cipher
|
||||
{
|
||||
/// <summary>
|
||||
/// Pool of encryption/decryption algorithms (ciphers).
|
||||
/// </summary>
|
||||
public sealed class CipherPool
|
||||
{
|
||||
private List<ICipherEngine> m_vCiphers = new List<ICipherEngine>();
|
||||
private static CipherPool m_poolGlobal = null;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the global cipher pool.
|
||||
/// </summary>
|
||||
public static CipherPool GlobalPool
|
||||
{
|
||||
get
|
||||
{
|
||||
if(m_poolGlobal != null) return m_poolGlobal;
|
||||
|
||||
m_poolGlobal = new CipherPool();
|
||||
m_poolGlobal.AddCipher(new StandardAesEngine());
|
||||
|
||||
return m_poolGlobal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove all cipher engines from the current pool.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
m_vCiphers.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a cipher engine to the pool.
|
||||
/// </summary>
|
||||
/// <param name="csEngine">Cipher engine to add. Must not be <c>null</c>.</param>
|
||||
public void AddCipher(ICipherEngine csEngine)
|
||||
{
|
||||
Debug.Assert(csEngine != null);
|
||||
if(csEngine == null) throw new ArgumentNullException("csEngine");
|
||||
|
||||
// Return if a cipher with that ID is registered already.
|
||||
for(int i = 0; i < m_vCiphers.Count; ++i)
|
||||
if(m_vCiphers[i].CipherUuid.EqualsValue(csEngine.CipherUuid))
|
||||
return;
|
||||
|
||||
m_vCiphers.Add(csEngine);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a cipher identified by its UUID.
|
||||
/// </summary>
|
||||
/// <param name="uuidCipher">UUID of the cipher to return.</param>
|
||||
/// <returns>Reference to the requested cipher. If the cipher is
|
||||
/// not found, <c>null</c> is returned.</returns>
|
||||
public ICipherEngine GetCipher(PwUuid uuidCipher)
|
||||
{
|
||||
foreach(ICipherEngine iEngine in m_vCiphers)
|
||||
{
|
||||
if(iEngine.CipherUuid.EqualsValue(uuidCipher))
|
||||
return iEngine;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the index of a cipher. This index is temporary and should
|
||||
/// not be stored or used to identify a cipher.
|
||||
/// </summary>
|
||||
/// <param name="uuidCipher">UUID of the cipher.</param>
|
||||
/// <returns>Index of the requested cipher. Returns <c>-1</c> if
|
||||
/// the specified cipher is not found.</returns>
|
||||
public int GetCipherIndex(PwUuid uuidCipher)
|
||||
{
|
||||
for(int i = 0; i < m_vCiphers.Count; ++i)
|
||||
{
|
||||
if(m_vCiphers[i].CipherUuid.EqualsValue(uuidCipher))
|
||||
return i;
|
||||
}
|
||||
|
||||
Debug.Assert(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the index of a cipher. This index is temporary and should
|
||||
/// not be stored or used to identify a cipher.
|
||||
/// </summary>
|
||||
/// <param name="strDisplayName">Name of the cipher. Note that
|
||||
/// multiple ciphers can have the same name. In this case, the
|
||||
/// first matching cipher is returned.</param>
|
||||
/// <returns>Cipher with the specified name or <c>-1</c> if
|
||||
/// no cipher with that name is found.</returns>
|
||||
public int GetCipherIndex(string strDisplayName)
|
||||
{
|
||||
for(int i = 0; i < m_vCiphers.Count; ++i)
|
||||
if(m_vCiphers[i].DisplayName == strDisplayName)
|
||||
return i;
|
||||
|
||||
Debug.Assert(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of cipher engines in this pool.
|
||||
/// </summary>
|
||||
public int EngineCount
|
||||
{
|
||||
get { return m_vCiphers.Count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the cipher engine at the specified position. Throws
|
||||
/// an exception if the index is invalid. You can use this
|
||||
/// to iterate over all ciphers, but do not use it to
|
||||
/// identify ciphers.
|
||||
/// </summary>
|
||||
/// <param name="nIndex">Index of the requested cipher engine.</param>
|
||||
/// <returns>Reference to the cipher engine at the specified
|
||||
/// position.</returns>
|
||||
public ICipherEngine this[int nIndex]
|
||||
{
|
||||
get
|
||||
{
|
||||
if((nIndex < 0) || (nIndex >= m_vCiphers.Count))
|
||||
throw new ArgumentOutOfRangeException("nIndex");
|
||||
|
||||
return m_vCiphers[nIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
66
ModernKeePassLib/Cryptography/Cipher/ICipherEngine.cs
Normal file
66
ModernKeePassLib/Cryptography/Cipher/ICipherEngine.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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.IO;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography.Cipher
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface of an encryption/decryption class.
|
||||
/// </summary>
|
||||
public interface ICipherEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// UUID of the engine. If you want to write an engine/plugin,
|
||||
/// please contact the KeePass team to obtain a new UUID.
|
||||
/// </summary>
|
||||
PwUuid CipherUuid
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// String displayed in the list of available encryption/decryption
|
||||
/// engines in the GUI.
|
||||
/// </summary>
|
||||
string DisplayName
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypt a stream.
|
||||
/// </summary>
|
||||
/// <param name="sPlainText">Stream to read the plain-text from.</param>
|
||||
/// <param name="pbKey">Key to use.</param>
|
||||
/// <param name="pbIV">Initialization vector.</param>
|
||||
/// <returns>Stream, from which the encrypted data can be read.</returns>
|
||||
Stream EncryptStream(Stream sPlainText, byte[] pbKey, byte[] pbIV);
|
||||
|
||||
/// <summary>
|
||||
/// Decrypt a stream.
|
||||
/// </summary>
|
||||
/// <param name="sEncrypted">Stream to read the encrypted data from.</param>
|
||||
/// <param name="pbKey">Key to use.</param>
|
||||
/// <param name="pbIV">Initialization vector.</param>
|
||||
/// <returns>Stream, from which the decrypted data can be read.</returns>
|
||||
Stream DecryptStream(Stream sEncrypted, byte[] pbKey, byte[] pbIV);
|
||||
}
|
||||
}
|
188
ModernKeePassLib/Cryptography/Cipher/Salsa20Cipher.cs
Normal file
188
ModernKeePassLib/Cryptography/Cipher/Salsa20Cipher.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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
|
||||
*/
|
||||
|
||||
// Implementation of the Salsa20 cipher, based on the eSTREAM submission.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography.Cipher
|
||||
{
|
||||
public sealed class Salsa20Cipher
|
||||
{
|
||||
private uint[] m_state = new uint[16];
|
||||
private uint[] m_x = new uint[16]; // Working buffer
|
||||
|
||||
private byte[] m_output = new byte[64];
|
||||
private int m_outputPos = 64;
|
||||
|
||||
private static readonly uint[] m_sigma = new uint[4]{
|
||||
0x61707865, 0x3320646E, 0x79622D32, 0x6B206574
|
||||
};
|
||||
|
||||
public Salsa20Cipher(byte[] pbKey32, byte[] pbIV8)
|
||||
{
|
||||
KeySetup(pbKey32);
|
||||
IvSetup(pbIV8);
|
||||
}
|
||||
|
||||
~Salsa20Cipher()
|
||||
{
|
||||
// Clear sensitive data
|
||||
Array.Clear(m_state, 0, m_state.Length);
|
||||
Array.Clear(m_x, 0, m_x.Length);
|
||||
}
|
||||
|
||||
private void NextOutput()
|
||||
{
|
||||
uint[] x = m_x; // Local alias for working buffer
|
||||
|
||||
// Compiler/runtime might remove array bound checks after this
|
||||
if(x.Length < 16) throw new InvalidOperationException();
|
||||
|
||||
Array.Copy(m_state, x, 16);
|
||||
|
||||
unchecked
|
||||
{
|
||||
for(int i = 0; i < 10; ++i) // (int i = 20; i > 0; i -= 2)
|
||||
{
|
||||
x[ 4] ^= Rotl32(x[ 0] + x[12], 7);
|
||||
x[ 8] ^= Rotl32(x[ 4] + x[ 0], 9);
|
||||
x[12] ^= Rotl32(x[ 8] + x[ 4], 13);
|
||||
x[ 0] ^= Rotl32(x[12] + x[ 8], 18);
|
||||
x[ 9] ^= Rotl32(x[ 5] + x[ 1], 7);
|
||||
x[13] ^= Rotl32(x[ 9] + x[ 5], 9);
|
||||
x[ 1] ^= Rotl32(x[13] + x[ 9], 13);
|
||||
x[ 5] ^= Rotl32(x[ 1] + x[13], 18);
|
||||
x[14] ^= Rotl32(x[10] + x[ 6], 7);
|
||||
x[ 2] ^= Rotl32(x[14] + x[10], 9);
|
||||
x[ 6] ^= Rotl32(x[ 2] + x[14], 13);
|
||||
x[10] ^= Rotl32(x[ 6] + x[ 2], 18);
|
||||
x[ 3] ^= Rotl32(x[15] + x[11], 7);
|
||||
x[ 7] ^= Rotl32(x[ 3] + x[15], 9);
|
||||
x[11] ^= Rotl32(x[ 7] + x[ 3], 13);
|
||||
x[15] ^= Rotl32(x[11] + x[ 7], 18);
|
||||
x[ 1] ^= Rotl32(x[ 0] + x[ 3], 7);
|
||||
x[ 2] ^= Rotl32(x[ 1] + x[ 0], 9);
|
||||
x[ 3] ^= Rotl32(x[ 2] + x[ 1], 13);
|
||||
x[ 0] ^= Rotl32(x[ 3] + x[ 2], 18);
|
||||
x[ 6] ^= Rotl32(x[ 5] + x[ 4], 7);
|
||||
x[ 7] ^= Rotl32(x[ 6] + x[ 5], 9);
|
||||
x[ 4] ^= Rotl32(x[ 7] + x[ 6], 13);
|
||||
x[ 5] ^= Rotl32(x[ 4] + x[ 7], 18);
|
||||
x[11] ^= Rotl32(x[10] + x[ 9], 7);
|
||||
x[ 8] ^= Rotl32(x[11] + x[10], 9);
|
||||
x[ 9] ^= Rotl32(x[ 8] + x[11], 13);
|
||||
x[10] ^= Rotl32(x[ 9] + x[ 8], 18);
|
||||
x[12] ^= Rotl32(x[15] + x[14], 7);
|
||||
x[13] ^= Rotl32(x[12] + x[15], 9);
|
||||
x[14] ^= Rotl32(x[13] + x[12], 13);
|
||||
x[15] ^= Rotl32(x[14] + x[13], 18);
|
||||
}
|
||||
|
||||
for(int i = 0; i < 16; ++i)
|
||||
x[i] += m_state[i];
|
||||
|
||||
for(int i = 0; i < 16; ++i)
|
||||
{
|
||||
m_output[i << 2] = (byte)x[i];
|
||||
m_output[(i << 2) + 1] = (byte)(x[i] >> 8);
|
||||
m_output[(i << 2) + 2] = (byte)(x[i] >> 16);
|
||||
m_output[(i << 2) + 3] = (byte)(x[i] >> 24);
|
||||
}
|
||||
|
||||
m_outputPos = 0;
|
||||
++m_state[8];
|
||||
if(m_state[8] == 0) ++m_state[9];
|
||||
}
|
||||
}
|
||||
|
||||
private static uint Rotl32(uint x, int b)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return ((x << b) | (x >> (32 - b)));
|
||||
}
|
||||
}
|
||||
|
||||
private static uint U8To32Little(byte[] pb, int iOffset)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return ((uint)pb[iOffset] | ((uint)pb[iOffset + 1] << 8) |
|
||||
((uint)pb[iOffset + 2] << 16) | ((uint)pb[iOffset + 3] << 24));
|
||||
}
|
||||
}
|
||||
|
||||
private void KeySetup(byte[] k)
|
||||
{
|
||||
if(k == null) throw new ArgumentNullException("k");
|
||||
if(k.Length != 32) throw new ArgumentException();
|
||||
|
||||
m_state[1] = U8To32Little(k, 0);
|
||||
m_state[2] = U8To32Little(k, 4);
|
||||
m_state[3] = U8To32Little(k, 8);
|
||||
m_state[4] = U8To32Little(k, 12);
|
||||
m_state[11] = U8To32Little(k, 16);
|
||||
m_state[12] = U8To32Little(k, 20);
|
||||
m_state[13] = U8To32Little(k, 24);
|
||||
m_state[14] = U8To32Little(k, 28);
|
||||
m_state[0] = m_sigma[0];
|
||||
m_state[5] = m_sigma[1];
|
||||
m_state[10] = m_sigma[2];
|
||||
m_state[15] = m_sigma[3];
|
||||
}
|
||||
|
||||
private void IvSetup(byte[] pbIV)
|
||||
{
|
||||
if(pbIV == null) throw new ArgumentNullException("pbIV");
|
||||
if(pbIV.Length != 8) throw new ArgumentException();
|
||||
|
||||
m_state[6] = U8To32Little(pbIV, 0);
|
||||
m_state[7] = U8To32Little(pbIV, 4);
|
||||
m_state[8] = 0;
|
||||
m_state[9] = 0;
|
||||
}
|
||||
|
||||
public void Encrypt(byte[] m, int nByteCount, bool bXor)
|
||||
{
|
||||
if(m == null) throw new ArgumentNullException("m");
|
||||
if(nByteCount > m.Length) throw new ArgumentException();
|
||||
|
||||
int nBytesRem = nByteCount, nOffset = 0;
|
||||
while(nBytesRem > 0)
|
||||
{
|
||||
Debug.Assert((m_outputPos >= 0) && (m_outputPos <= 64));
|
||||
if(m_outputPos == 64) NextOutput();
|
||||
Debug.Assert(m_outputPos < 64);
|
||||
|
||||
int nCopy = Math.Min(64 - m_outputPos, nBytesRem);
|
||||
|
||||
if(bXor) MemUtil.XorArray(m_output, m_outputPos, m, nOffset, nCopy);
|
||||
else Array.Copy(m_output, m_outputPos, m, nOffset, nCopy);
|
||||
|
||||
m_outputPos += nCopy;
|
||||
nBytesRem -= nCopy;
|
||||
nOffset += nCopy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
146
ModernKeePassLib/Cryptography/Cipher/StandardAesEngine.cs
Normal file
146
ModernKeePassLib/Cryptography/Cipher/StandardAesEngine.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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.IO;
|
||||
|
||||
using ModernKeePassLib.Resources;
|
||||
using ModernKeePassLib.Serialization;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography.Cipher
|
||||
{
|
||||
/// <summary>
|
||||
/// Standard AES cipher implementation.
|
||||
/// </summary>
|
||||
public sealed class StandardAesEngine : ICipherEngine
|
||||
{
|
||||
// private const CipherMode m_rCipherMode = CipherMode.CBC;
|
||||
// private const PaddingMode m_rCipherPadding = PaddingMode.PKCS7;
|
||||
|
||||
private static PwUuid m_uuidAes = null;
|
||||
|
||||
/// <summary>
|
||||
/// UUID of the cipher engine. This ID uniquely identifies the
|
||||
/// AES engine. Must not be used by other ciphers.
|
||||
/// </summary>
|
||||
public static PwUuid AesUuid
|
||||
{
|
||||
get
|
||||
{
|
||||
if(m_uuidAes == null)
|
||||
{
|
||||
m_uuidAes = new PwUuid(new byte[]{
|
||||
0x31, 0xC1, 0xF2, 0xE6, 0xBF, 0x71, 0x43, 0x50,
|
||||
0xBE, 0x58, 0x05, 0x21, 0x6A, 0xFC, 0x5A, 0xFF });
|
||||
}
|
||||
|
||||
return m_uuidAes;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the UUID of this cipher engine as <c>PwUuid</c> object.
|
||||
/// </summary>
|
||||
public PwUuid CipherUuid
|
||||
{
|
||||
get { return StandardAesEngine.AesUuid; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a displayable name describing this cipher engine.
|
||||
/// </summary>
|
||||
public string DisplayName { get { return KLRes.EncAlgorithmAes; } }
|
||||
|
||||
private static void ValidateArguments(Stream stream, bool bEncrypt, byte[] pbKey, byte[] pbIV)
|
||||
{
|
||||
Debug.Assert(stream != null); if(stream == null) throw new ArgumentNullException("stream");
|
||||
|
||||
Debug.Assert(pbKey != null); if(pbKey == null) throw new ArgumentNullException("pbKey");
|
||||
Debug.Assert(pbKey.Length == 32);
|
||||
if(pbKey.Length != 32) throw new ArgumentException("Key must be 256 bits wide!");
|
||||
|
||||
Debug.Assert(pbIV != null); if(pbIV == null) throw new ArgumentNullException("pbIV");
|
||||
Debug.Assert(pbIV.Length == 16);
|
||||
if(pbIV.Length != 16) throw new ArgumentException("Initialization vector must be 128 bits wide!");
|
||||
|
||||
if(bEncrypt)
|
||||
{
|
||||
Debug.Assert(stream.CanWrite);
|
||||
if(stream.CanWrite == false) throw new ArgumentException("Stream must be writable!");
|
||||
}
|
||||
else // Decrypt
|
||||
{
|
||||
Debug.Assert(stream.CanRead);
|
||||
if(stream.CanRead == false) throw new ArgumentException("Encrypted stream must be readable!");
|
||||
}
|
||||
}
|
||||
|
||||
private static Stream CreateStream(Stream s, bool bEncrypt, byte[] pbKey, byte[] pbIV)
|
||||
{
|
||||
StandardAesEngine.ValidateArguments(s, bEncrypt, pbKey, pbIV);
|
||||
|
||||
return new CryptoStream( s, "AES_CBC_PKCS7", bEncrypt, pbKey, pbIV);
|
||||
|
||||
}
|
||||
#if false
|
||||
|
||||
RijndaelManaged r = new RijndaelManaged();
|
||||
|
||||
if(r.BlockSize != 128) // AES block size
|
||||
{
|
||||
Debug.Assert(false);
|
||||
r.BlockSize = 128;
|
||||
}
|
||||
|
||||
byte[] pbLocalIV = new byte[16];
|
||||
Array.Copy(pbIV, pbLocalIV, 16);
|
||||
r.IV = pbLocalIV;
|
||||
|
||||
byte[] pbLocalKey = new byte[32];
|
||||
Array.Copy(pbKey, pbLocalKey, 32);
|
||||
r.KeySize = 256;
|
||||
r.Key = pbLocalKey;
|
||||
|
||||
r.Mode = m_rCipherMode;
|
||||
r.Padding = m_rCipherPadding;
|
||||
|
||||
ICryptoTransform iTransform = (bEncrypt ? r.CreateEncryptor() : r.CreateDecryptor());
|
||||
Debug.Assert(iTransform != null);
|
||||
if(iTransform == null) throw new SecurityException("Unable to create Rijndael transform!");
|
||||
|
||||
return new CryptoStream(s, iTransform, bEncrypt ? CryptoStreamMode.Write :
|
||||
CryptoStreamMode.Read);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
public Stream EncryptStream(Stream sPlainText, byte[] pbKey, byte[] pbIV)
|
||||
{
|
||||
return StandardAesEngine.CreateStream(sPlainText, true, pbKey, pbIV);
|
||||
}
|
||||
|
||||
public Stream DecryptStream(Stream sEncrypted, byte[] pbKey, byte[] pbIV)
|
||||
{
|
||||
return StandardAesEngine.CreateStream(sEncrypted, false, pbKey, pbIV);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
331
ModernKeePassLib/Cryptography/CryptoRandom.cs
Normal file
331
ModernKeePassLib/Cryptography/CryptoRandom.cs
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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 Windows.Security.Cryptography;
|
||||
//using System.Windows.Forms;
|
||||
//using System.Drawing;
|
||||
|
||||
|
||||
namespace ModernKeePassLib.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Cryptographically strong random number generator. The returned values
|
||||
/// are unpredictable and cannot be reproduced.
|
||||
/// <c>CryptoRandom</c> is a singleton class.
|
||||
/// </summary>
|
||||
public sealed class CryptoRandom
|
||||
{
|
||||
//private byte[] m_pbEntropyPool = new byte[64];
|
||||
//private uint m_uCounter;
|
||||
//private RNGCryptoServiceProvider m_rng = new RNGCryptoServiceProvider();
|
||||
//private ulong m_uGeneratedBytesCount = 0;
|
||||
|
||||
// private object m_oSyncRoot = new object();
|
||||
|
||||
private static CryptoRandom m_pInstance = null;
|
||||
public static CryptoRandom Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if(m_pInstance != null) return m_pInstance;
|
||||
|
||||
m_pInstance = new CryptoRandom();
|
||||
return m_pInstance;
|
||||
}
|
||||
}
|
||||
|
||||
#if KeePassWinRT
|
||||
private CryptoRandom()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the internal seed of the random number generator based
|
||||
/// on entropy data.
|
||||
/// This method is thread-safe.
|
||||
/// </summary>
|
||||
/// <param name="pbEntropy">Entropy bytes.</param>
|
||||
public void AddEntropy(byte[] pbEntropy)
|
||||
{
|
||||
// Not used in WinRT version
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a number of cryptographically strong random bytes.
|
||||
/// This method is thread-safe.
|
||||
/// </summary>
|
||||
/// <param name="uRequestedBytes">Number of requested random bytes.</param>
|
||||
/// <returns>A byte array consisting of <paramref name="uRequestedBytes" />
|
||||
/// random bytes.</returns>
|
||||
public byte[] GetRandomBytes(uint uRequestedBytes)
|
||||
{
|
||||
if (uRequestedBytes == 0) return new byte[0]; // Allow zero-length array
|
||||
|
||||
byte[] pbRes;
|
||||
|
||||
Windows.Storage.Streams.IBuffer buffer = CryptographicBuffer.GenerateRandom(uRequestedBytes);
|
||||
CryptographicBuffer.CopyToByteArray(buffer, out pbRes);
|
||||
return pbRes;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
/// <summary>
|
||||
/// Get the number of random bytes that this instance generated so far.
|
||||
/// Note that this number can be higher than the number of random bytes
|
||||
/// actually requested using the <c>GetRandomBytes</c> method.
|
||||
/// </summary>
|
||||
public ulong GeneratedBytesCount
|
||||
{
|
||||
get
|
||||
{
|
||||
ulong u;
|
||||
lock(m_oSyncRoot) { u = m_uGeneratedBytesCount; }
|
||||
return u;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event that is triggered whenever the internal <c>GenerateRandom256</c>
|
||||
/// method is called to generate random bytes.
|
||||
/// </summary>
|
||||
public event EventHandler GenerateRandom256Pre;
|
||||
|
||||
private CryptoRandom()
|
||||
{
|
||||
Random r = new Random();
|
||||
m_uCounter = (uint)r.Next();
|
||||
|
||||
AddEntropy(GetSystemData(r));
|
||||
AddEntropy(GetCspData());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the internal seed of the random number generator based
|
||||
/// on entropy data.
|
||||
/// This method is thread-safe.
|
||||
/// </summary>
|
||||
/// <param name="pbEntropy">Entropy bytes.</param>
|
||||
public void AddEntropy(byte[] pbEntropy)
|
||||
{
|
||||
|
||||
if(pbEntropy == null) { Debug.Assert(false); return; }
|
||||
if(pbEntropy.Length == 0) { Debug.Assert(false); return; }
|
||||
|
||||
byte[] pbNewData = pbEntropy;
|
||||
if(pbEntropy.Length >= 64)
|
||||
{
|
||||
#if !KeePassLibSD
|
||||
SHA512Managed shaNew = new SHA512Managed();
|
||||
#else
|
||||
SHA256Managed shaNew = new SHA256Managed();
|
||||
#endif
|
||||
pbNewData = shaNew.ComputeHash(pbEntropy);
|
||||
}
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
lock(m_oSyncRoot)
|
||||
{
|
||||
ms.Write(m_pbEntropyPool, 0, m_pbEntropyPool.Length);
|
||||
ms.Write(pbNewData, 0, pbNewData.Length);
|
||||
|
||||
byte[] pbFinal = ms.ToArray();
|
||||
#if !KeePassLibSD
|
||||
Debug.Assert(pbFinal.Length == (64 + pbNewData.Length));
|
||||
SHA512Managed shaPool = new SHA512Managed();
|
||||
#else
|
||||
SHA256Managed shaPool = new SHA256Managed();
|
||||
#endif
|
||||
m_pbEntropyPool = shaPool.ComputeHash(pbFinal);
|
||||
}
|
||||
ms.Close();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static byte[] GetSystemData(Random rWeak)
|
||||
{
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
byte[] pb;
|
||||
|
||||
pb = MemUtil.UInt32ToBytes((uint)Environment.TickCount);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
|
||||
pb = TimeUtil.PackTime(DateTime.Now);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
|
||||
#if !KeePassLibSD
|
||||
Point pt = Cursor.Position;
|
||||
pb = MemUtil.UInt32ToBytes((uint)pt.X);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt32ToBytes((uint)pt.Y);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
#endif
|
||||
|
||||
pb = MemUtil.UInt32ToBytes((uint)rWeak.Next());
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
|
||||
pb = MemUtil.UInt32ToBytes((uint)NativeLib.GetPlatformID());
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
|
||||
#if !KeePassLibSD
|
||||
try
|
||||
{
|
||||
pb = MemUtil.UInt32ToBytes((uint)Environment.ProcessorCount);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt64ToBytes((ulong)Environment.WorkingSet);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
|
||||
Version v = Environment.OSVersion.Version;
|
||||
int nv = (v.Major << 28) + (v.MajorRevision << 24) +
|
||||
(v.Minor << 20) + (v.MinorRevision << 16) +
|
||||
(v.Revision << 12) + v.Build;
|
||||
pb = MemUtil.UInt32ToBytes((uint)nv);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
|
||||
Process p = Process.GetCurrentProcess();
|
||||
pb = MemUtil.UInt64ToBytes((ulong)p.Handle.ToInt64());
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt32ToBytes((uint)p.HandleCount);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt32ToBytes((uint)p.Id);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt64ToBytes((ulong)p.NonpagedSystemMemorySize64);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt64ToBytes((ulong)p.PagedMemorySize64);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt64ToBytes((ulong)p.PagedSystemMemorySize64);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt64ToBytes((ulong)p.PeakPagedMemorySize64);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt64ToBytes((ulong)p.PeakVirtualMemorySize64);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt64ToBytes((ulong)p.PeakWorkingSet64);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt64ToBytes((ulong)p.PrivateMemorySize64);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt64ToBytes((ulong)p.StartTime.ToBinary());
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt64ToBytes((ulong)p.VirtualMemorySize64);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
pb = MemUtil.UInt64ToBytes((ulong)p.WorkingSet64);
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
|
||||
// Not supported in Mono 1.2.6:
|
||||
// pb = MemUtil.UInt32ToBytes((uint)p.SessionId);
|
||||
// ms.Write(pb, 0, pb.Length);
|
||||
}
|
||||
catch(Exception) { }
|
||||
#endif
|
||||
|
||||
pb = Guid.NewGuid().ToByteArray();
|
||||
ms.Write(pb, 0, pb.Length);
|
||||
|
||||
byte[] pbAll = ms.ToArray();
|
||||
ms.Close();
|
||||
return pbAll;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private byte[] GetCspData()
|
||||
{
|
||||
uint length = 32;
|
||||
byte[] pbCspRandom = new byte[length];
|
||||
|
||||
Windows.Storage.Streams.IBuffer buffer = CryptographicBuffer.GenerateRandom(length);
|
||||
|
||||
CryptographicBuffer.CopyToByteArray(buffer, pbCspRandom);
|
||||
//m_rng.GetBytes(pbCspRandom);
|
||||
return pbCspRandom;
|
||||
}
|
||||
|
||||
private byte[] GenerateRandom256()
|
||||
{
|
||||
|
||||
if(this.GenerateRandom256Pre != null)
|
||||
this.GenerateRandom256Pre(this, EventArgs.Empty);
|
||||
|
||||
byte[] pbFinal;
|
||||
lock(m_oSyncRoot)
|
||||
{
|
||||
unchecked { m_uCounter += 386047; } // Prime number
|
||||
byte[] pbCounter = MemUtil.UInt32ToBytes(m_uCounter);
|
||||
|
||||
byte[] pbCspRandom = GetCspData();
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
ms.Write(m_pbEntropyPool, 0, m_pbEntropyPool.Length);
|
||||
ms.Write(pbCounter, 0, pbCounter.Length);
|
||||
ms.Write(pbCspRandom, 0, pbCspRandom.Length);
|
||||
pbFinal = ms.ToArray();
|
||||
Debug.Assert(pbFinal.Length == (m_pbEntropyPool.Length +
|
||||
pbCounter.Length + pbCspRandom.Length));
|
||||
ms.Close();
|
||||
|
||||
m_uGeneratedBytesCount += 32;
|
||||
}
|
||||
|
||||
SHA256Managed sha256 = new SHA256Managed();
|
||||
return sha256.ComputeHash(pbFinal);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a number of cryptographically strong random bytes.
|
||||
/// This method is thread-safe.
|
||||
/// </summary>
|
||||
/// <param name="uRequestedBytes">Number of requested random bytes.</param>
|
||||
/// <returns>A byte array consisting of <paramref name="uRequestedBytes" />
|
||||
/// random bytes.</returns>
|
||||
public byte[] GetRandomBytes(uint uRequestedBytes)
|
||||
{
|
||||
if(uRequestedBytes == 0) return new byte[0]; // Allow zero-length array
|
||||
|
||||
byte[] pbRes = new byte[uRequestedBytes];
|
||||
long lPos = 0;
|
||||
|
||||
while(uRequestedBytes != 0)
|
||||
{
|
||||
byte[] pbRandom256 = GenerateRandom256();
|
||||
Debug.Assert(pbRandom256.Length == 32);
|
||||
|
||||
long lCopy = (long)((uRequestedBytes < 32) ? uRequestedBytes : 32);
|
||||
|
||||
#if !KeePassLibSD
|
||||
Array.Copy(pbRandom256, 0, pbRes, lPos, lCopy);
|
||||
#else
|
||||
Array.Copy(pbRandom256, 0, pbRes, (int)lPos, (int)lCopy);
|
||||
#endif
|
||||
|
||||
lPos += lCopy;
|
||||
uRequestedBytes -= (uint)lCopy;
|
||||
}
|
||||
|
||||
Debug.Assert((int)lPos == pbRes.Length);
|
||||
return pbRes;
|
||||
}
|
||||
|
||||
#endif // !KeePassWinRT
|
||||
|
||||
}
|
||||
}
|
208
ModernKeePassLib/Cryptography/CryptoRandomStream.cs
Normal file
208
ModernKeePassLib/Cryptography/CryptoRandomStream.cs
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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 ModernKeePassLib.Cryptography.Cipher;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithms supported by <c>CryptoRandomStream</c>.
|
||||
/// </summary>
|
||||
public enum CrsAlgorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Not supported.
|
||||
/// </summary>
|
||||
Null = 0,
|
||||
|
||||
/// <summary>
|
||||
/// A variant of the ARCFour algorithm (RC4 incompatible).
|
||||
/// </summary>
|
||||
ArcFourVariant = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Salsa20 stream cipher algorithm.
|
||||
/// </summary>
|
||||
Salsa20 = 2,
|
||||
|
||||
Count = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A random stream class. The class is initialized using random
|
||||
/// bytes provided by the caller. The produced stream has random
|
||||
/// properties, but for the same seed always the same stream
|
||||
/// is produced, i.e. this class can be used as stream cipher.
|
||||
/// </summary>
|
||||
public sealed class CryptoRandomStream
|
||||
{
|
||||
private CrsAlgorithm m_crsAlgorithm;
|
||||
|
||||
private byte[] m_pbState = null;
|
||||
private byte m_i = 0;
|
||||
private byte m_j = 0;
|
||||
|
||||
private Salsa20Cipher m_salsa20 = null;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new cryptographically secure random stream object.
|
||||
/// </summary>
|
||||
/// <param name="genAlgorithm">Algorithm to use.</param>
|
||||
/// <param name="pbKey">Initialization key. Must not be <c>null</c> and
|
||||
/// must contain at least 1 byte.</param>
|
||||
/// <exception cref="System.ArgumentNullException">Thrown if the
|
||||
/// <paramref name="pbKey" /> parameter is <c>null</c>.</exception>
|
||||
/// <exception cref="System.ArgumentException">Thrown if the
|
||||
/// <paramref name="pbKey" /> parameter contains no bytes or the
|
||||
/// algorithm is unknown.</exception>
|
||||
public CryptoRandomStream(CrsAlgorithm genAlgorithm, byte[] pbKey)
|
||||
{
|
||||
m_crsAlgorithm = genAlgorithm;
|
||||
|
||||
Debug.Assert(pbKey != null); if(pbKey == null) throw new ArgumentNullException("pbKey");
|
||||
|
||||
uint uKeyLen = (uint)pbKey.Length;
|
||||
Debug.Assert(uKeyLen != 0); if(uKeyLen == 0) throw new ArgumentException();
|
||||
|
||||
if(genAlgorithm == CrsAlgorithm.ArcFourVariant)
|
||||
{
|
||||
// Fill the state linearly
|
||||
m_pbState = new byte[256];
|
||||
for(uint w = 0; w < 256; ++w) m_pbState[w] = (byte)w;
|
||||
|
||||
unchecked
|
||||
{
|
||||
byte j = 0, t;
|
||||
uint inxKey = 0;
|
||||
for(uint w = 0; w < 256; ++w) // Key setup
|
||||
{
|
||||
j += (byte)(m_pbState[w] + pbKey[inxKey]);
|
||||
|
||||
t = m_pbState[0]; // Swap entries
|
||||
m_pbState[0] = m_pbState[j];
|
||||
m_pbState[j] = t;
|
||||
|
||||
++inxKey;
|
||||
if(inxKey >= uKeyLen) inxKey = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GetRandomBytes(512); // Increases security, see cryptanalysis
|
||||
}
|
||||
else if(genAlgorithm == CrsAlgorithm.Salsa20)
|
||||
{
|
||||
byte[] pbKey32 = SHA256Managed.Instance.ComputeHash(pbKey);
|
||||
|
||||
byte[] pbIV = new byte[]{ 0xE8, 0x30, 0x09, 0x4B,
|
||||
0x97, 0x20, 0x5D, 0x2A }; // Unique constant
|
||||
|
||||
m_salsa20 = new Salsa20Cipher(pbKey32, pbIV);
|
||||
|
||||
}
|
||||
else // Unknown algorithm
|
||||
{
|
||||
Debug.Assert(false);
|
||||
throw new ArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get <paramref name="uRequestedCount" /> random bytes.
|
||||
/// </summary>
|
||||
/// <param name="uRequestedCount">Number of random bytes to retrieve.</param>
|
||||
/// <returns>Returns <paramref name="uRequestedCount" /> random bytes.</returns>
|
||||
public byte[] GetRandomBytes(uint uRequestedCount)
|
||||
{
|
||||
if(uRequestedCount == 0) return new byte[0];
|
||||
|
||||
byte[] pbRet = new byte[uRequestedCount];
|
||||
|
||||
if(m_crsAlgorithm == CrsAlgorithm.ArcFourVariant)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
for(uint w = 0; w < uRequestedCount; ++w)
|
||||
{
|
||||
++m_i;
|
||||
m_j += m_pbState[m_i];
|
||||
|
||||
byte t = m_pbState[m_i]; // Swap entries
|
||||
m_pbState[m_i] = m_pbState[m_j];
|
||||
m_pbState[m_j] = t;
|
||||
|
||||
t = (byte)(m_pbState[m_i] + m_pbState[m_j]);
|
||||
pbRet[w] = m_pbState[t];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(m_crsAlgorithm == CrsAlgorithm.Salsa20)
|
||||
m_salsa20.Encrypt(pbRet, pbRet.Length, false);
|
||||
else { Debug.Assert(false); }
|
||||
|
||||
return pbRet;
|
||||
}
|
||||
|
||||
public ulong GetRandomUInt64()
|
||||
{
|
||||
byte[] pb = GetRandomBytes(8);
|
||||
|
||||
unchecked
|
||||
{
|
||||
return ((ulong)pb[0]) | ((ulong)pb[1] << 8) |
|
||||
((ulong)pb[2] << 16) | ((ulong)pb[3] << 24) |
|
||||
((ulong)pb[4] << 32) | ((ulong)pb[5] << 40) |
|
||||
((ulong)pb[6] << 48) | ((ulong)pb[7] << 56);
|
||||
}
|
||||
}
|
||||
|
||||
#if CRSBENCHMARK
|
||||
public static string Benchmark()
|
||||
{
|
||||
int nRounds = 2000000;
|
||||
|
||||
string str = "ArcFour small: " + BenchTime(CrsAlgorithm.ArcFourVariant,
|
||||
nRounds, 16).ToString() + "\r\n";
|
||||
str += "ArcFour big: " + BenchTime(CrsAlgorithm.ArcFourVariant,
|
||||
32, 2 * 1024 * 1024).ToString() + "\r\n";
|
||||
str += "Salsa20 small: " + BenchTime(CrsAlgorithm.Salsa20,
|
||||
nRounds, 16).ToString() + "\r\n";
|
||||
str += "Salsa20 big: " + BenchTime(CrsAlgorithm.Salsa20,
|
||||
32, 2 * 1024 * 1024).ToString();
|
||||
return str;
|
||||
}
|
||||
|
||||
private static int BenchTime(CrsAlgorithm cra, int nRounds, int nDataSize)
|
||||
{
|
||||
byte[] pbKey = new byte[4] { 0x00, 0x01, 0x02, 0x03 };
|
||||
|
||||
int nStart = Environment.TickCount;
|
||||
for(int i = 0; i < nRounds; ++i)
|
||||
{
|
||||
CryptoRandomStream c = new CryptoRandomStream(cra, pbKey);
|
||||
c.GetRandomBytes((uint)nDataSize);
|
||||
}
|
||||
int nEnd = Environment.TickCount;
|
||||
|
||||
return (nEnd - nStart);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
207
ModernKeePassLib/Cryptography/HashingStreamEx.cs
Normal file
207
ModernKeePassLib/Cryptography/HashingStreamEx.cs
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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.IO;
|
||||
using Windows.Security.Cryptography.Core;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography
|
||||
{
|
||||
public sealed class HashingStreamEx : Stream
|
||||
{
|
||||
private Stream m_sBaseStream;
|
||||
private bool m_bWriting;
|
||||
private Queue<byte[]> m_DataToHash;
|
||||
|
||||
public byte[] Hash
|
||||
{
|
||||
get
|
||||
{
|
||||
int len = 0;
|
||||
foreach (byte[] block in m_DataToHash)
|
||||
{
|
||||
len += block.Length;
|
||||
}
|
||||
byte[] dataToHash = new byte[len];
|
||||
int pos = 0;
|
||||
while(m_DataToHash.Count > 0)
|
||||
{
|
||||
byte[] block = m_DataToHash.Dequeue();
|
||||
Array.Copy(block, 0, dataToHash, pos, block.Length);
|
||||
pos += block.Length;
|
||||
}
|
||||
|
||||
byte[] hash = SHA256Managed.Instance.ComputeHash(dataToHash);
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get { return !m_bWriting; }
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { return m_bWriting; }
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get { return m_sBaseStream.Length; }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { return m_sBaseStream.Position; }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
public HashingStreamEx(Stream sBaseStream, bool bWriting, CryptographicHash hashAlgorithm)
|
||||
{
|
||||
if (sBaseStream == null) throw new ArgumentNullException("sBaseStream");
|
||||
|
||||
m_sBaseStream = sBaseStream;
|
||||
m_bWriting = bWriting;
|
||||
|
||||
#if KeePassWinRT
|
||||
|
||||
m_DataToHash = new Queue<byte[]>();
|
||||
|
||||
|
||||
#else
|
||||
#if !KeePassLibSD
|
||||
m_hash = (hashAlgorithm ?? new SHA256Managed());
|
||||
#else // KeePassLibSD
|
||||
m_hash = null;
|
||||
|
||||
try { m_hash = HashAlgorithm.Create("SHA256"); }
|
||||
catch(Exception) { }
|
||||
try { if(m_hash == null) m_hash = HashAlgorithm.Create(); }
|
||||
catch(Exception) { }
|
||||
#endif
|
||||
#endif // KeePassWinRT
|
||||
|
||||
|
||||
#if TODO
|
||||
// Bert TODO: For the time being, only built-in Hash algorithm are supported.
|
||||
if (m_hash == null) { Debug.Assert(false); return; }
|
||||
// Validate hash algorithm
|
||||
if((!m_hash.CanReuseTransform) || (!m_hash.CanTransformMultipleBlocks) ||
|
||||
(m_hash.InputBlockSize != 1) || (m_hash.OutputBlockSize != 1))
|
||||
{
|
||||
#if DEBUG
|
||||
MessageService.ShowWarning("Broken HashAlgorithm object in HashingStreamEx.");
|
||||
#endif
|
||||
m_hash = null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
m_sBaseStream.Flush();
|
||||
}
|
||||
|
||||
#if TODO
|
||||
public override void Close()
|
||||
{
|
||||
|
||||
if(m_hash != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_hash.TransformFinalBlock(new byte[0], 0, 0);
|
||||
|
||||
m_pbFinalHash = m_hash.Hash;
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
m_hash = null;
|
||||
}
|
||||
|
||||
m_sBaseStream.Close();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
public override long Seek(long lOffset, SeekOrigin soOrigin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long lValue)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override int Read(byte[] pbBuffer, int nOffset, int nCount)
|
||||
{
|
||||
|
||||
if (m_bWriting) throw new InvalidOperationException();
|
||||
|
||||
int nRead = m_sBaseStream.Read(pbBuffer, nOffset, nCount);
|
||||
|
||||
// Mono bug workaround (LaunchPad 798910)
|
||||
int nPartialRead = nRead;
|
||||
while ((nRead < nCount) && (nPartialRead != 0))
|
||||
{
|
||||
nPartialRead = m_sBaseStream.Read(pbBuffer, nOffset + nRead,
|
||||
nCount - nRead);
|
||||
nRead += nPartialRead;
|
||||
}
|
||||
|
||||
byte[] pbOrg = new byte[nRead];
|
||||
Array.Copy(pbBuffer, pbOrg, nRead);
|
||||
m_DataToHash.Enqueue(pbOrg);
|
||||
|
||||
return nRead;
|
||||
}
|
||||
|
||||
public override void Write(byte[] pbBuffer, int nOffset, int nCount)
|
||||
{
|
||||
// BERT TODO: Not implemented.
|
||||
Debug.Assert(false);
|
||||
#if TODO
|
||||
if(!m_bWriting) throw new InvalidOperationException();
|
||||
|
||||
#if DEBUG
|
||||
byte[] pbOrg = new byte[pbBuffer.Length];
|
||||
Array.Copy(pbBuffer, pbOrg, pbBuffer.Length);
|
||||
#endif
|
||||
|
||||
if((m_hash != null) && (nCount > 0))
|
||||
m_hash.TransformBlock(pbBuffer, nOffset, nCount, pbBuffer, nOffset);
|
||||
|
||||
#if DEBUG
|
||||
Debug.Assert(MemUtil.ArraysEqual(pbBuffer, pbOrg));
|
||||
#endif
|
||||
|
||||
m_sBaseStream.Write(pbBuffer, nOffset, nCount);
|
||||
|
||||
#endif // TODO
|
||||
}
|
||||
}
|
||||
}
|
89
ModernKeePassLib/Cryptography/HmacOtp.cs
Normal file
89
ModernKeePassLib/Cryptography/HmacOtp.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#if !KeePassLibSD
|
||||
namespace ModernKeePassLib.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Generate HMAC-based one-time passwords as specified in RFC 4226.
|
||||
/// </summary>
|
||||
public static class HmacOtp
|
||||
{
|
||||
private static readonly uint[] vDigitsPower = new uint[]{ 1, 10, 100,
|
||||
1000, 10000, 100000, 1000000, 10000000, 100000000 };
|
||||
|
||||
public static string Generate(byte[] pbSecret, ulong uFactor,
|
||||
uint uCodeDigits, bool bAddChecksum, int iTruncationOffset)
|
||||
{
|
||||
Debug.Assert(false, "Not yet implemented");
|
||||
return null;
|
||||
#if TODO
|
||||
byte[] pbText = MemUtil.UInt64ToBytes(uFactor);
|
||||
Array.Reverse(pbText); // Big-Endian
|
||||
|
||||
HMACSHA1 hsha1 = new HMACSHA1(pbSecret);
|
||||
byte[] pbHash = hsha1.ComputeHash(pbText);
|
||||
|
||||
uint uOffset = (uint)(pbHash[pbHash.Length - 1] & 0xF);
|
||||
if((iTruncationOffset >= 0) && (iTruncationOffset < (pbHash.Length - 4)))
|
||||
uOffset = (uint)iTruncationOffset;
|
||||
|
||||
uint uBinary = (uint)(((pbHash[uOffset] & 0x7F) << 24) |
|
||||
((pbHash[uOffset + 1] & 0xFF) << 16) |
|
||||
((pbHash[uOffset + 2] & 0xFF) << 8) |
|
||||
(pbHash[uOffset + 3] & 0xFF));
|
||||
|
||||
uint uOtp = (uBinary % vDigitsPower[uCodeDigits]);
|
||||
if(bAddChecksum)
|
||||
uOtp = ((uOtp * 10) + CalculateChecksum(uOtp, uCodeDigits));
|
||||
|
||||
uint uDigits = (bAddChecksum ? (uCodeDigits + 1) : uCodeDigits);
|
||||
return uOtp.ToString().PadLeft((int)uDigits, '0');
|
||||
#endif
|
||||
}
|
||||
|
||||
private static readonly uint[] vDoubleDigits = new uint[]{ 0, 2, 4, 6, 8,
|
||||
1, 3, 5, 7, 9 };
|
||||
|
||||
private static uint CalculateChecksum(uint uNum, uint uDigits)
|
||||
{
|
||||
bool bDoubleDigit = true;
|
||||
uint uTotal = 0;
|
||||
|
||||
while(0 < uDigits--)
|
||||
{
|
||||
uint uDigit = (uNum % 10);
|
||||
uNum /= 10;
|
||||
|
||||
if(bDoubleDigit) uDigit = vDoubleDigits[uDigit];
|
||||
|
||||
uTotal += uDigit;
|
||||
bDoubleDigit = !bDoubleDigit;
|
||||
}
|
||||
|
||||
uint uResult = (uTotal % 10);
|
||||
if(uResult != 0) uResult = 10 - uResult;
|
||||
|
||||
return uResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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.Diagnostics;
|
||||
|
||||
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());
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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-2012 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.EqualsValue(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.EqualsValue(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,173 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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.Diagnostics;
|
||||
|
||||
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> 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 == '[')
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
private static string ExpandPattern(string strPattern)
|
||||
{
|
||||
Debug.Assert(strPattern != null); if(strPattern == null) 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;
|
||||
}
|
||||
}
|
||||
}
|
318
ModernKeePassLib/Cryptography/PasswordGenerator/PwCharSet.cs
Normal file
318
ModernKeePassLib/Cryptography/PasswordGenerator/PwCharSet.cs
Normal file
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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.Diagnostics;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography.PasswordGenerator
|
||||
{
|
||||
public sealed class PwCharSet
|
||||
{
|
||||
public const string UpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
public const string LowerCase = "abcdefghijklmnopqrstuvwxyz";
|
||||
public const string Digits = "0123456789";
|
||||
|
||||
public const string UpperConsonants = "BCDFGHJKLMNPQRSTVWXYZ";
|
||||
public const string LowerConsonants = "bcdfghjklmnpqrstvwxyz";
|
||||
public const string UpperVowels = "AEIOU";
|
||||
public const string LowerVowels = "aeiou";
|
||||
|
||||
public const string Punctuation = @",.;:";
|
||||
public const string Brackets = @"[]{}()<>";
|
||||
|
||||
public const string PrintableAsciiSpecial = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
||||
|
||||
public const string UpperHex = "0123456789ABCDEF";
|
||||
public const string LowerHex = "0123456789abcdef";
|
||||
|
||||
public const string Invalid = "\t\r\n";
|
||||
public const string LookAlike = @"O0l1I|";
|
||||
|
||||
private const int CharTabSize = (0x10000 / 8);
|
||||
|
||||
private List<char> m_vChars = new List<char>();
|
||||
private byte[] m_vTab = new byte[CharTabSize];
|
||||
|
||||
private string m_strHighAnsi = string.Empty;
|
||||
private string m_strSpecial = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new, empty character set collection object.
|
||||
/// </summary>
|
||||
public PwCharSet()
|
||||
{
|
||||
this.Initialize(true);
|
||||
}
|
||||
|
||||
public PwCharSet(string strCharSet)
|
||||
{
|
||||
this.Initialize(true);
|
||||
this.Add(strCharSet);
|
||||
}
|
||||
|
||||
private PwCharSet(bool bFullInitialize)
|
||||
{
|
||||
this.Initialize(bFullInitialize);
|
||||
}
|
||||
|
||||
private void Initialize(bool bFullInitialize)
|
||||
{
|
||||
this.Clear();
|
||||
|
||||
if(bFullInitialize == false) return;
|
||||
|
||||
StringBuilder sbHighAnsi = new StringBuilder();
|
||||
for(char ch = '~'; ch < 255; ++ch)
|
||||
sbHighAnsi.Append(ch);
|
||||
m_strHighAnsi = sbHighAnsi.ToString();
|
||||
|
||||
PwCharSet pcs = new PwCharSet(false);
|
||||
pcs.AddRange('!', '/');
|
||||
pcs.AddRange(':', '@');
|
||||
pcs.AddRange('[', '`');
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
public string SpecialChars { get { return m_strSpecial; } }
|
||||
public string HighAnsiChars { get { return m_strHighAnsi; } }
|
||||
|
||||
/// <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(this.Contains(ch) == false) 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(this.Contains(ch) == false)
|
||||
{
|
||||
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)
|
||||
this.Add(ch);
|
||||
}
|
||||
|
||||
public void Add(string strCharSet1, string strCharSet2)
|
||||
{
|
||||
this.Add(strCharSet1);
|
||||
this.Add(strCharSet2);
|
||||
}
|
||||
|
||||
public void Add(string strCharSet1, string strCharSet2, string strCharSet3)
|
||||
{
|
||||
this.Add(strCharSet1);
|
||||
this.Add(strCharSet2);
|
||||
this.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)
|
||||
this.Add(ch);
|
||||
|
||||
this.Add(chMax);
|
||||
}
|
||||
|
||||
public bool AddCharSet(char chCharSetIdentifier)
|
||||
{
|
||||
bool bResult = true;
|
||||
|
||||
switch(chCharSetIdentifier)
|
||||
{
|
||||
case 'a': this.Add(PwCharSet.LowerCase, PwCharSet.Digits); break;
|
||||
case 'A': this.Add(PwCharSet.LowerCase, PwCharSet.UpperCase,
|
||||
PwCharSet.Digits); break;
|
||||
case 'U': this.Add(PwCharSet.UpperCase, PwCharSet.Digits); break;
|
||||
case 'c': this.Add(PwCharSet.LowerConsonants); break;
|
||||
case 'C': this.Add(PwCharSet.LowerConsonants,
|
||||
PwCharSet.UpperConsonants); break;
|
||||
case 'z': this.Add(PwCharSet.UpperConsonants); break;
|
||||
case 'd': this.Add(PwCharSet.Digits); break; // Digit
|
||||
case 'h': this.Add(PwCharSet.LowerHex); break;
|
||||
case 'H': this.Add(PwCharSet.UpperHex); break;
|
||||
case 'l': this.Add(PwCharSet.LowerCase); break;
|
||||
case 'L': this.Add(PwCharSet.LowerCase, PwCharSet.UpperCase); break;
|
||||
case 'u': this.Add(PwCharSet.UpperCase); break;
|
||||
case 'p': this.Add(PwCharSet.Punctuation); break;
|
||||
case 'b': this.Add(PwCharSet.Brackets); break;
|
||||
case 's': this.Add(PwCharSet.PrintableAsciiSpecial); break;
|
||||
case 'S': this.Add(PwCharSet.UpperCase, PwCharSet.LowerCase);
|
||||
this.Add(PwCharSet.Digits, PwCharSet.PrintableAsciiSpecial); break;
|
||||
case 'v': this.Add(PwCharSet.LowerVowels); break;
|
||||
case 'V': this.Add(PwCharSet.LowerVowels, PwCharSet.UpperVowels); break;
|
||||
case 'Z': this.Add(PwCharSet.UpperVowels); break;
|
||||
case 'x': this.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(this.Contains(strCharacters) == false)
|
||||
return false;
|
||||
|
||||
return this.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(this.RemoveIfAllExist(PwCharSet.UpperCase) ? 'U' : '_');
|
||||
sb.Append(this.RemoveIfAllExist(PwCharSet.LowerCase) ? 'L' : '_');
|
||||
sb.Append(this.RemoveIfAllExist(PwCharSet.Digits) ? 'D' : '_');
|
||||
sb.Append(this.RemoveIfAllExist(m_strSpecial) ? 'S' : '_');
|
||||
sb.Append(this.RemoveIfAllExist(PwCharSet.Punctuation) ? 'P' : '_');
|
||||
sb.Append(this.RemoveIfAllExist(@"-") ? 'm' : '_');
|
||||
sb.Append(this.RemoveIfAllExist(@"_") ? 'u' : '_');
|
||||
sb.Append(this.RemoveIfAllExist(@" ") ? 's' : '_');
|
||||
sb.Append(this.RemoveIfAllExist(PwCharSet.Brackets) ? 'B' : '_');
|
||||
sb.Append(this.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] != '_') this.Add(PwCharSet.UpperCase);
|
||||
if(strRanges[1] != '_') this.Add(PwCharSet.LowerCase);
|
||||
if(strRanges[2] != '_') this.Add(PwCharSet.Digits);
|
||||
if(strRanges[3] != '_') this.Add(m_strSpecial);
|
||||
if(strRanges[4] != '_') this.Add(PwCharSet.Punctuation);
|
||||
if(strRanges[5] != '_') this.Add('-');
|
||||
if(strRanges[6] != '_') this.Add('_');
|
||||
if(strRanges[7] != '_') this.Add(' ');
|
||||
if(strRanges[8] != '_') this.Add(PwCharSet.Brackets);
|
||||
if(strRanges[9] != '_') this.Add(m_strHighAnsi);
|
||||
}
|
||||
}
|
||||
}
|
146
ModernKeePassLib/Cryptography/PasswordGenerator/PwGenerator.cs
Normal file
146
ModernKeePassLib/Cryptography/PasswordGenerator/PwGenerator.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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.Diagnostics;
|
||||
|
||||
using ModernKeePassLib.Security;
|
||||
|
||||
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");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private static CryptoRandomStream CreateCryptoStream(byte[] pbAdditionalEntropy)
|
||||
{
|
||||
byte[] pbKey = CryptoRandom.Instance.GetRandomBytes(256);
|
||||
|
||||
// Mix in additional entropy
|
||||
if((pbAdditionalEntropy != null) && (pbAdditionalEntropy.Length > 0))
|
||||
{
|
||||
for(int nKeyPos = 0; nKeyPos < pbKey.Length; ++nKeyPos)
|
||||
pbKey[nKeyPos] ^= pbAdditionalEntropy[nKeyPos % pbAdditionalEntropy.Length];
|
||||
}
|
||||
|
||||
return new CryptoRandomStream(CrsAlgorithm.Salsa20, 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 ShufflePassword(char[] pPassword,
|
||||
CryptoRandomStream crsRandomSource)
|
||||
{
|
||||
Debug.Assert(pPassword != null); if(pPassword == null) return;
|
||||
Debug.Assert(crsRandomSource != null); if(crsRandomSource == null) return;
|
||||
|
||||
if(pPassword.Length <= 1) return; // Nothing to shuffle
|
||||
|
||||
for(int nSelect = 0; nSelect < pPassword.Length; ++nSelect)
|
||||
{
|
||||
ulong uRandomIndex = crsRandomSource.GetRandomUInt64();
|
||||
uRandomIndex %= (ulong)(pPassword.Length - nSelect);
|
||||
|
||||
char chTemp = pPassword[nSelect];
|
||||
pPassword[nSelect] = pPassword[nSelect + (int)uRandomIndex];
|
||||
pPassword[nSelect + (int)uRandomIndex] = chTemp;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
274
ModernKeePassLib/Cryptography/PasswordGenerator/PwProfile.cs
Normal file
274
ModernKeePassLib/Cryptography/PasswordGenerator/PwProfile.cs
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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.ComponentModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
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;
|
||||
|
||||
byte[] pbUtf8 = psPassword.ReadUtf8();
|
||||
char[] vChars = StrUtil.Utf8.GetChars(pbUtf8);
|
||||
|
||||
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((@"!#$%&'*+,./:;=?@^").IndexOf(ch) >= 0) pcs.Add(pcs.SpecialChars);
|
||||
else if(ch == ' ') pcs.Add(' ');
|
||||
else if(ch == '-') pcs.Add('-');
|
||||
else if(ch == '_') pcs.Add('_');
|
||||
else if(ch == '\"') pcs.Add(pcs.SpecialChars);
|
||||
else if(ch == '\\') pcs.Add(pcs.SpecialChars);
|
||||
else if((@"()[]{}<>").IndexOf(ch) >= 0) pcs.Add(PwCharSet.Brackets);
|
||||
else if((ch >= '~') && (ch <= 255)) pcs.Add(pcs.HighAnsiChars);
|
||||
else pcs.Add(ch);
|
||||
}
|
||||
|
||||
Array.Clear(vChars, 0, vChars.Length);
|
||||
MemUtil.ZeroByteArray(pbUtf8);
|
||||
return pp;
|
||||
}
|
||||
|
||||
public bool HasSecurityReducingOption()
|
||||
{
|
||||
return (m_bNoLookAlike || m_bNoRepeat || (m_strExclude.Length > 0));
|
||||
}
|
||||
}
|
||||
}
|
539
ModernKeePassLib/Cryptography/PopularPasswords.cs
Normal file
539
ModernKeePassLib/Cryptography/PopularPasswords.cs
Normal file
@@ -0,0 +1,539 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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 ModernKeePassLib.Utility;
|
||||
|
||||
#if !KeePassLibSD
|
||||
namespace ModernKeePassLib.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Bloom filter-based popular password checking.
|
||||
/// </summary>
|
||||
public static class PopularPasswords
|
||||
{
|
||||
private const int PpcTableSize = 8192 * 8; // Bits, multiple of 64
|
||||
|
||||
// Bits set: 32433 of 65536
|
||||
// Hash functions: 32
|
||||
// Phi (bits unset ratio) estimation: 0.505455388896019
|
||||
// Exact Phi: 0.505111694335938
|
||||
// False positives ratio: 1.67583063859565E-10
|
||||
private static readonly ulong[] PpcTable = {
|
||||
0x60383D3A85560B9BUL, 0x2578CE9D37C6AEB7UL, 0xF509A5743FD03228UL,
|
||||
0x19B7455E8933EE56UL, 0x5EA419ADCFD9C20EUL, 0xEA618EFC0B37A162UL,
|
||||
0xE0FD4D1FFF1CE415UL, 0x7A649E0301BB6060UL, 0x80D9CD9F9EEB603DUL,
|
||||
0x47D6010D0D6E6CDEUL, 0x2552708C589EB554UL, 0x073F1A3DB3267502UL,
|
||||
0x3313FEC2A2FEA475UL, 0x4593665C44934FEBUL, 0x410A301A23660395UL,
|
||||
0x6AD06DA533FF5659UL, 0x423DAF86F3E41F4AUL, 0x82F035A971C6FD18UL,
|
||||
0xB5E9139F28C93223UL, 0x1D07C3F4160585CAUL, 0x24B01EDB6B23E2C5UL,
|
||||
0xD52F25B724F936C9UL, 0x8018392517836928UL, 0x3AA4C0F8E181EDA2UL,
|
||||
0x8D93683EF7D52529UL, 0x6164BB6208114460UL, 0x737A04D8FEF3D88FUL,
|
||||
0x3400097098D5C2CBUL, 0x3C2B9ABE5C455B2EUL, 0x3A3819973AB32DA2UL,
|
||||
0x38ACB428510AF40BUL, 0x83320D5114B74771UL, 0xC25BEC333B90DCD1UL,
|
||||
0x0E9F412FBA3813D1UL, 0x047E31E3098EB2B8UL, 0xBB686AC643F1741FUL,
|
||||
0x0BE22E9C0EF0E8F2UL, 0x65AA9504E5F40D31UL, 0xE018DF5D64C62AC7UL,
|
||||
0x17020E9A7EFA12EDUL, 0xFC12A7C16006DE82UL, 0x8DE4747E3745346DUL,
|
||||
0x31D8C051A43CECAFUL, 0xBE9AFBEF127C1B12UL, 0xAEE94B4B808BBEE2UL,
|
||||
0x3A0099CA32835B41UL, 0x59EB3173468D8C49UL, 0x6F89DB1E6DAAE9E1UL,
|
||||
0x4C1ADAA837E968E4UL, 0x6E3593A56C682769UL, 0x022AD591689B5B82UL,
|
||||
0x4AC33861ED978032UL, 0xF6F476E4E6A1318DUL, 0x2DA690A11AA05A23UL,
|
||||
0x916FC56378C29D77UL, 0xAB3238BE22294659UL, 0x2D73A29019B28C77UL,
|
||||
0xAAF26C12EC9C3C42UL, 0x058A278A24B334F9UL, 0x033BD18FB8D9BACDUL,
|
||||
0x8B3833596008B07CUL, 0x280B6D093333E5E5UL, 0x2128DBE126CA3E1EUL,
|
||||
0xCCF09769382472D8UL, 0x0CB6E495BD90CED6UL, 0x1303A37577C01C5AUL,
|
||||
0xC8BBF4734FC34C53UL, 0x1B38B72B10F86CD5UL, 0x5098E2D6C1892E51UL,
|
||||
0x2DD8065B79DB5380UL, 0x5B9A1A6D6A2292B7UL, 0xC70F751604D0497CUL,
|
||||
0x911E08D7363B5213UL, 0x9F2E245273308D2EUL, 0x64D354827957F50EUL,
|
||||
0x09856750F560342CUL, 0xDE091F26603F0E70UL, 0xDDE6B4E76173E3B1UL,
|
||||
0xC1584AE1B26FA08EUL, 0x1EA29887837838D2UL, 0x6D7643FC67B15C54UL,
|
||||
0x921E60571ED103EAUL, 0x63EB1EB33E7AFFF1UL, 0x80BA4D1F95BFD615UL,
|
||||
0xEC8A1D4FC1A6B8E0UL, 0x2C46861B6DB17D1AUL, 0x01F05D06927E443BUL,
|
||||
0x6172EC2EABEAD454UL, 0x21B8726C6F7C4102UL, 0x3C016CD9945C72ECUL,
|
||||
0x708F77B2C0E8B665UL, 0xFC35BE2BB88974DAUL, 0x805897A33702BD61UL,
|
||||
0x9A93367A6041226CUL, 0xFDAB188B6158F6BEUL, 0x5F21014A065E918CUL,
|
||||
0xF4381DD77772D19CUL, 0xC664B6358AA85011UL, 0xF2639D7B3E2307E6UL,
|
||||
0x3FA000D4A5A9C37AUL, 0x8F45D116ED8DC70FUL, 0x8CB8758E45C140D0UL,
|
||||
0x49832B46D716236DUL, 0xCC8E4961A93065B8UL, 0x8A996533EDACEB0EUL,
|
||||
0x15B35155EC56FAC1UL, 0xE7E0C6C05A9F1885UL, 0x05914F9A1D1C79F9UL,
|
||||
0x730000A30B6725F0UL, 0xC95E671F8E543780UL, 0x47D68382400AF94EUL,
|
||||
0x1A27F2734FE2249AUL, 0x828079C332D9C0ABUL, 0x2E9BC798EA09170EUL,
|
||||
0x6B7CDAC829018C91UL, 0x7B89604901736993UL, 0xABE4EB26F47608F0UL,
|
||||
0x70D5FDC88A0FF1B1UL, 0x5A1F0BAB9AB8A158UL, 0xDC89AE0A735C51A4UL,
|
||||
0x36C1EA01E9C89B84UL, 0x3A9757AF204096DBUL, 0x1D56C8328540F963UL,
|
||||
0x910A8694692472FAUL, 0x697192C9DF145604UL, 0xB20F7A4438712AA2UL,
|
||||
0xE8C99185243F4896UL, 0xFBC8970EDBC39CA7UL, 0x33485403868C3761UL,
|
||||
0xAFA97DDEDB1D6AD8UL, 0x54A1A6F24476A3BBUL, 0xFE4E078B184BDB7FUL,
|
||||
0x5ED1543919754CD8UL, 0x86F8C775160FC08CUL, 0x9B4098F57019040DUL,
|
||||
0x039518BBE841327BUL, 0x111D0D420A3F5F6AUL, 0x0666067346AF34ACUL,
|
||||
0xD43F1D14EB239B9BUL, 0xA6BB91FEB5618F5BUL, 0xA2B5218B202409ADUL,
|
||||
0xC004FA688C3AC25EUL, 0xF0E2D9EA2935E1DCUL, 0x380B31CFA2F2AF43UL,
|
||||
0x50E050AE426250EAUL, 0x628ED94D1AA8F55BUL, 0xF8EB0654F0166311UL,
|
||||
0x1F8858D26DDA5CC5UL, 0x931425D11CB1EFEBUL, 0xF661D461DC1A05D3UL,
|
||||
0x7B75ED7EC6936DA8UL, 0x8713C59690985202UL, 0xF61D6F93F07C0E85UL,
|
||||
0xFD1771F6711D6F4FUL, 0x5835A67E1B11419FUL, 0x33EF08ABD56A1050UL,
|
||||
0x55B5D0043FA2C01CUL, 0x53316ED963B92D9DUL, 0x6A8C93744E521EDBUL,
|
||||
0x083E948062EB9543UL, 0x1C15289B3189AFB1UL, 0xA6A0A5053AE2212DUL,
|
||||
0x6573AF7F01FAFF3BUL, 0x58B6F034CFCFE843UL, 0xEB2837CA5AEA6AEDUL,
|
||||
0x633E7897097AC328UL, 0x7FA91789B6CCEE82UL, 0xBEE2402F4E7D65EEUL,
|
||||
0x616A103EC8FB0DBEUL, 0x65991F9FB25E13FCUL, 0x54EA8A3FADEC1F4BUL,
|
||||
0x6D497C5ACDEA0E7AUL, 0x5865045E8CA18527UL, 0xA406C09215ABD61FUL,
|
||||
0x68F81F5745FC9875UL, 0xE496D850CEFF3FA9UL, 0xD225C88D63212CB1UL,
|
||||
0x37676390525116D2UL, 0x415614AB14188A7DUL, 0xABE58EBC1F6DDC63UL,
|
||||
0xDE10312B2C25D28CUL, 0x86C86D7A0B847635UL, 0x408B511D584DC3DCUL,
|
||||
0x6711FCC14B303FEDUL, 0x1284DF9CC6972023UL, 0xC3CE0B33141BFA8FUL,
|
||||
0x0F3F58367D4A1819UL, 0x9313F83058FBE6D0UL, 0x6FCA5EF39B8E2F47UL,
|
||||
0xA90F5C95D887756DUL, 0x96C4E2AD85D5AF6EUL, 0x0ED68A81F526F0A0UL,
|
||||
0x53E4472DB4255A35UL, 0xAC581015134D58A6UL, 0x12C000D85C644FC7UL,
|
||||
0x124D489B2C0FE6E4UL, 0x8FF83531C6F5D61AUL, 0x132BD6488304F73BUL,
|
||||
0x110E99BC59604CB9UL, 0xC28186ACBC940C9BUL, 0x2094C07F48141230UL,
|
||||
0x65FB9881A5053589UL, 0x940A3E6D72F09D69UL, 0x972A922CB14BA66EUL,
|
||||
0x8D07E59C6DDD4327UL, 0xCB67F993F820157CUL, 0x65B7A54E5FB2ED6CUL,
|
||||
0xC235828849576653UL, 0xA695F85479467538UL, 0x9E2BA885E63C4243UL,
|
||||
0xDE64A6A5EF84C222UL, 0xC2AB9AF302080621UL, 0x88DBA09B87FA0734UL,
|
||||
0xDF002765B44D02E1UL, 0xD50D8D90587CD820UL, 0x1B68B70ED179EFE1UL,
|
||||
0xD6E77F8EC26AE95CUL, 0xEE57EB7C45051872UL, 0x4D2B445F36A7F9FDUL,
|
||||
0x5502ABB8BB14D7F1UL, 0xAF2C0DF0406FA901UL, 0x6522833444BF4A83UL,
|
||||
0xD7CB2E3FC691BE8DUL, 0x4F36F70D2E80D19AUL, 0xF6945FE911D4923BUL,
|
||||
0xE3C6FE1EA47399C1UL, 0xF09EA1B2F837702CUL, 0x5122537CF97B5CB5UL,
|
||||
0x0C8202B70E9BF154UL, 0x68B554AB58EB5E68UL, 0x7BF9B8052C9BEADEUL,
|
||||
0x33612BFCD303810DUL, 0x03E38CF67B37DC53UL, 0x2BFDFF8691F37D5CUL,
|
||||
0x4AB483D1CB1D07F6UL, 0xF071A58640639A5CUL, 0x9D6B98169B745CE1UL,
|
||||
0x5F42D3E870FDCD93UL, 0x4EDF04404F258238UL, 0x2EAB6E10D65C9BB3UL,
|
||||
0x5BB71411EF78DAD2UL, 0x0DE8128636A5D689UL, 0x18FDD1F484DC9365UL,
|
||||
0x9896B8896941DA5BUL, 0x8BEF8E3BA4448E5FUL, 0x963A1E977CB1D2CAUL,
|
||||
0x02BCF5F068D52851UL, 0x0CD783F09BFBE381UL, 0x350DA833D8C5DB47UL,
|
||||
0x8D444C914D795C43UL, 0x8A00B4DFC44D9476UL, 0x4B36CBEC089E55FDUL,
|
||||
0xD9D2FA1B0AC66211UL, 0x6C7FC30FA31A8B60UL, 0x9EF4504CC985AD6BUL,
|
||||
0x8F2E7E5E0C00EE73UL, 0x819131CFEEBEA069UL, 0xB1E406A863E7A1B4UL,
|
||||
0x501F072FF1F2AB67UL, 0xDE578BFC5ADBC264UL, 0xCDD66A09C8E13881UL,
|
||||
0x4D443460CE52957FUL, 0x3B198C267976ECFAUL, 0x6B98323D8BD26522UL,
|
||||
0x80161F6A489E4BF8UL, 0xE03A8AFCC7AE6872UL, 0x2484BD95A305AB27UL,
|
||||
0x6ADDAA46BF25DD0EUL, 0xA429D8B00100477CUL, 0x55AEDB88A074BF2CUL,
|
||||
0x63D9F9021AB8F5F3UL, 0x37858538A10C265CUL, 0xEF54C2CE9D063149UL,
|
||||
0xFA5CE5AF33E2C136UL, 0xE601A559D0C391D7UL, 0x7C4ED29BBF57DC7EUL,
|
||||
0x8FD0D4146DE9E900UL, 0xB58ABFA6CE6C0733UL, 0xF8D7F7743B33EAFFUL,
|
||||
0x453FA782F454643CUL, 0xD01752C21AF21E66UL, 0xA50BB7913EAF05DFUL,
|
||||
0x966D5B140B2F4189UL, 0x956F5638AFF3D148UL, 0x93FAA838420E8AB3UL,
|
||||
0x715E26043071EABDUL, 0x01E7B458B5FD3A41UL, 0x5CFA99C4CC0492AAUL,
|
||||
0x761FD391C3623044UL, 0xD39E44E9DB96B5BCUL, 0x8806C544F0534A07UL,
|
||||
0x9B225CAFE97EAAC1UL, 0xEAE5E18583492767UL, 0x6B4E51E4C297F096UL,
|
||||
0xFC512662EF47E41DUL, 0xB6AC60427DB46F8BUL, 0x8F137F3DB4429C9DUL,
|
||||
0x04C65FBEAE9FD8D0UL, 0xEB72305958AE5022UL, 0xAA93AA14BCA2961EUL,
|
||||
0x6C7547F9456CA37AUL, 0xEE6094871615BA34UL, 0x489BC8EDE0940402UL,
|
||||
0x1108AEFAAD892229UL, 0x673B8B1CF6BED23EUL, 0xFDB781A75FD94DEAUL,
|
||||
0x11D9E0F5D914A7BEUL, 0x02830D07F018143DUL, 0x9B3163B8188FD2BAUL,
|
||||
0x32C1BEC97D06117EUL, 0x697268B761240CFFUL, 0xBD89CE3037C2E7A9UL,
|
||||
0xF21C158125B19600UL, 0x632CB1931601B70AUL, 0x7BB3FB131338085CUL,
|
||||
0xA9C06689B8138384UL, 0x161CCBF83EBDC2A1UL, 0x2CF83C01A80B7935UL,
|
||||
0x9E51FE393B8E2FF0UL, 0xFE96E52B1606C1A7UL, 0x5E20DFB87F81ACCEUL,
|
||||
0xF95DB9602CDAE467UL, 0xDEA155CD35555FEBUL, 0xF0669B810F70CDC6UL,
|
||||
0xD36C2FBEB6A449ACUL, 0xCE500C6621C0A445UL, 0x41308909E366460AUL,
|
||||
0xAC4D8178DA0CEC24UL, 0xC69049179ED09F7DUL, 0x36B608A0BA2FD848UL,
|
||||
0xDF511894DD9568B4UL, 0xB3BFDF78EC861A6CUL, 0xCD50F39D19848153UL,
|
||||
0xD2C1BC57E78A408CUL, 0x1E6613EFBB11B5EBUL, 0xF58E30D2D90F73D3UL,
|
||||
0xCCB5E2F5E168D742UL, 0xEE97259469BDB672UL, 0x6784D35AF65935A8UL,
|
||||
0x71032765ADED1FE8UL, 0x4BBF2FE54D9B72E3UL, 0x5A1BB7831E876A05UL,
|
||||
0x12A8FC949EE91686UL, 0x8296F8FA83BD112CUL, 0xAAA7E3BFF64D34D5UL,
|
||||
0x0301655E1794EE4BUL, 0x1E547C011BBF30E1UL, 0x39D74FEC536F31D6UL,
|
||||
0x3C31A7478B1815BAUL, 0x525C774F82D5836EUL, 0xECF7186DC612FD8CUL,
|
||||
0x96B7C4EDD1F3536FUL, 0x7E8C21F19C08541CUL, 0xEE92DB0CF91E4B09UL,
|
||||
0xF666190D1591AE5DUL, 0x5E9B45102C895361UL, 0x9A95597AAE5C905DUL,
|
||||
0x6E1272E5BB93F93FUL, 0x0E39E612402BFCF8UL, 0x576C9E8CA2A3B35EUL,
|
||||
0x7E2E629996D0C35FUL, 0xC95DFF54E3524FCCUL, 0x260F9DEBDEB0E5CBUL,
|
||||
0x577B6C6640BAF1ABUL, 0xCA76677779CA358EUL, 0x9E2714BEBCFDB144UL,
|
||||
0xD660595CE30FD3EEUL, 0x72DE172D55A5706EUL, 0xB4C84D564489D420UL,
|
||||
0x160AA2B9399D5A9DUL, 0x2906ECE619DAC4D2UL, 0x12CE8E8E68A4C317UL,
|
||||
0x6BE2DFE89901CAA1UL, 0xEE1D68158102EB77UL, 0x64EB75E45BDA1AC5UL,
|
||||
0xEFECF9F98720B55DUL, 0x41CDF813931315BFUL, 0x5F1E4F50CF98FFD4UL,
|
||||
0xE69E09EED12E173BUL, 0x89A3707F0396FF65UL, 0x81E36B9DF4FFB492UL,
|
||||
0x58C32E883D4DE6DDUL, 0x2D4725C2A5F0B469UL, 0x6B2B9C27CC421CACUL,
|
||||
0x3C30F2AD966800C7UL, 0xFF74938BB76B8A7CUL, 0x52B5C99114FD93FAUL,
|
||||
0x51647EDCA6C104DAUL, 0xEB47684CF796DF4EUL, 0x376D74A5AB14BD71UL,
|
||||
0xF0871FEF8E9DAA3EUL, 0x1D65B134B2E045B6UL, 0x9DC8C0D8623BBA48UL,
|
||||
0xAD6FC3C59DBDADF4UL, 0x66F6EBA55488B569UL, 0xB00D53E0E2D38F0AUL,
|
||||
0x43A4212CEAD34593UL, 0x44724185FF7019FFUL, 0x50F46061432B3635UL,
|
||||
0x880AA4C24E6B320BUL, 0xCAFCB3409A0DB43FUL, 0xA7F1A13DEF47514BUL,
|
||||
0x3DC8A385A698220CUL, 0xFA17F82E30B85580UL, 0x430E7F0E88655F47UL,
|
||||
0x45A1566013837B47UL, 0x84B2306D2292804EUL, 0xE7A3AF21D074E419UL,
|
||||
0x09D08E2C5E569D4DUL, 0x84228F8908383FA2UL, 0xC34079610C8D3E82UL,
|
||||
0x66C96426C54A5453UL, 0xD41F164117D32C93UL, 0x7829A66BF1FEC186UL,
|
||||
0x4BB6846694BDFC18UL, 0x857D1C1C01352C01UL, 0xAB8E68BA85402A45UL,
|
||||
0x74B3C4F101FE76C8UL, 0x6CF482CFAFB29FFEUL, 0x28B174A18F4DC3D1UL,
|
||||
0x833C3425B2AA3755UL, 0x8AA58A32747F4432UL, 0xFE7B9FB4BCE3CD58UL,
|
||||
0xB0836B2C16FA5553UL, 0x1D08EE6861BF3F23UL, 0x0FAE41E914562DF3UL,
|
||||
0xB10A2E041937FC57UL, 0xDA60BB363415BF4CUL, 0xEEC67DBAB4CF4F0AUL,
|
||||
0x9A6ED59FCC923B5CUL, 0x9A913C01A8EC7A83UL, 0xAD4779F2F9C7721FUL,
|
||||
0x2BF0B7D105BE7459UL, 0x189EFA9AD5195EC6UL, 0xB5C9A2DD64B2A903UL,
|
||||
0x5BCD642B2C2FD32CUL, 0xFED3FBF78CB0891FUL, 0x1ED958EE3C36DD3FUL,
|
||||
0x030F5DE9CA65E97CUL, 0xBB5BCF8C931B85FEUL, 0xFD128759EA1D8061UL,
|
||||
0x2C0238AC416BE6BCUL, 0xBB018584EEACFA27UL, 0xCEA7288C1964DE15UL,
|
||||
0x7EA5C3840F29AA4DUL, 0x5DA841BA609E4A50UL, 0xE53AF84845985EB1UL,
|
||||
0x93264DA9487183E4UL, 0xC3A4E367AF6D8D15UL, 0xDD4EB6450577BAF8UL,
|
||||
0x2AA3093EE2C658ACUL, 0x3D036EC45055C580UL, 0xDDEDB34341C5B7DFUL,
|
||||
0x524FFBDC4A1FAC90UL, 0x1B9D63DE13D82907UL, 0x69F9BAF0E868B640UL,
|
||||
0xFC1A453A9253013CUL, 0x08B900DECAA77377UL, 0xFF24C72324153C59UL,
|
||||
0x6182C1285C507A9BUL, 0x4E6680A54A03CCC8UL, 0x7165680200B67F1FUL,
|
||||
0xC3290B26A07DCE5BUL, 0x2AD16584AA5BECE9UL, 0x5F10DF677C91B05EUL,
|
||||
0x4BE1B0E2334B198AUL, 0xEA2466E4F4E4406DUL, 0x6ECAA92FF91E6F1DUL,
|
||||
0x0267738EFA75CADDUL, 0x4282ED10A0EBFCF2UL, 0xD3F84CE8E1685271UL,
|
||||
0xB667ED35716CA215UL, 0x97B4623D70DB7FA8UL, 0xB7BA3AA5E6C2E7CBUL,
|
||||
0x8942B2F97118255BUL, 0x009050F842FB52ADUL, 0x114F5511999F5BD5UL,
|
||||
0x70C1CAAF1E83F00AUL, 0xAC8EE25D462BB1AAUL, 0x63EEF42AD4E1BED9UL,
|
||||
0x58DFBB3D22D3D1A5UL, 0x82B0027C0C63D816UL, 0x48D038F08F3D848BUL,
|
||||
0xCE262D5F9A12610EUL, 0xA54BF51C21BD0167UL, 0xF3645F6FB948397DUL,
|
||||
0x9188AE58532DA501UL, 0xEC90B0E1479DB767UL, 0x37F4886B83724F80UL,
|
||||
0x232B8FF20ACD95AFUL, 0x88A228285D6BCDF0UL, 0x321FB91600259AEEUL,
|
||||
0xA1F875F161D18E5EUL, 0x5B6087CDA21AEA0CUL, 0x0156923ED1A3D5F1UL,
|
||||
0xC2892C8A6133B5D3UL, 0x015CA4DF0EA6354DUL, 0x5E25EB261B69A7D4UL,
|
||||
0xAAA8CF0C012EFBA7UL, 0xCF3466248C37868BUL, 0x0D744514BD1D82C0UL,
|
||||
0xB00FF1431EDDF490UL, 0xC79B86A0E3A8AB08UL, 0xFC361529BC9F1252UL,
|
||||
0x869285653FB82865UL, 0x9F1C7A17546339ABUL, 0xE31AA66DBD5C4760UL,
|
||||
0x51B9D2A765E0FC31UL, 0x31F39528C4CD13D8UL, 0x16C6C35B0D3A341DUL,
|
||||
0x90296B1B0F28E2CDUL, 0x36338472A8DB5830UL, 0xA648E6D44DF14F87UL,
|
||||
0x93E231E65EB1823FUL, 0x95AA7B9D08E2B627UL, 0x7932D149374700C7UL,
|
||||
0x09EFE0A8BF245193UL, 0x742AA63BCEAFD6D8UL, 0x82D4BC5FEDF158B7UL,
|
||||
0x02CDEA673CFF150DUL, 0xD8D7B5813B602D15UL, 0xA5A7B670EF15A5EDUL,
|
||||
0x4C08E580A1D46AF2UL, 0xC3CA9B905D035647UL, 0x6A39ABB02F6F1B83UL,
|
||||
0xD2EC2169F4D02436UL, 0x8E6AEA4DF8515AF2UL, 0x7B3DD4A8693CA2DAUL,
|
||||
0xC2ABF17A50AEC383UL, 0xD4FB84F8B6D4F709UL, 0x2839A3EAA2E4C8A7UL,
|
||||
0x5D5FD278FE10E1E9UL, 0x5610DDF74125D5A7UL, 0xA484B0B83461DCEAUL,
|
||||
0xA511920C0A502369UL, 0xC53F30C6A5394CA4UL, 0x528799285D304DD4UL,
|
||||
0xF6D7914CB252BB48UL, 0x892129CB52E65D15UL, 0x15A81B70519ACE6FUL,
|
||||
0x5CFBFFD7A2A1C630UL, 0x3B900509C82DF46DUL, 0x19C3CE05D66D5FFCUL,
|
||||
0x937D521A4A4799A0UL, 0xD0AE34A6EAD7207DUL, 0x3258A69F1D1A1B38UL,
|
||||
0xB173E3255723CC02UL, 0xD7E48FEF7F414F1BUL, 0xDCEBA75F5C761ABEUL,
|
||||
0x6DA10C618DEA0D17UL, 0x423FA8B05954FBD1UL, 0x7E73C2E7D923F3C9UL,
|
||||
0xC22E21C927C684D1UL, 0x756BAA758764685FUL, 0x8C90B4C4E741D880UL,
|
||||
0x1B658C9F4B41D846UL, 0x5D80C14094366707UL, 0xB55FED3E03C00F2DUL,
|
||||
0x9B69EB7964C69C83UL, 0x356ED81C9494DADDUL, 0x7599AFF0B2A339D6UL,
|
||||
0xA5EBFD25C9B5816BUL, 0xA481DC1C8995E1EFUL, 0xE42C63DF0D402397UL,
|
||||
0x3B497B4C30873BAAUL, 0xA950B78BA8772C96UL, 0xD46308D4C76F115DUL,
|
||||
0x73714A4ACA76A857UL, 0x0DA86B958FF8CB7DUL, 0xEB61F617B90E0A75UL,
|
||||
0xD6106C9B39F51F55UL, 0xB179F73A6BD23B59UL, 0xE7F056E50104A460UL,
|
||||
0xBC5B5387634A8642UL, 0xE1678D8752996AF4UL, 0xB508F3D394664A4BUL,
|
||||
0xC88536DC4A219B0FUL, 0x39964CBB8CE367B1UL, 0xD51E211D5E9E1417UL,
|
||||
0x6821B97B496870F2UL, 0xA596257350CA0A99UL, 0x6D051EE2C49D4D1DUL,
|
||||
0xCB426AD61AA8D9B5UL, 0x5FFD3A4062B06D22UL, 0xDAD37BF2A4C594EBUL,
|
||||
0x6B9CC848E2B0C686UL, 0x19B4232F3BC622AEUL, 0x70C13C7E5950B702UL,
|
||||
0x383318CA622101ACUL, 0xD9647C028CD1C4DFUL, 0x006D123BC553B93CUL,
|
||||
0x2CA9D7D896EAE722UL, 0xF19872AC8A0BD5A8UL, 0x59838578EB9E8E5CUL,
|
||||
0xB948621EE99B27D4UL, 0x2B470E6036E0E387UL, 0xD0A7E8F0C8A32A84UL,
|
||||
0xCBF869271A8E0914UL, 0x705F76A5EA4437CFUL, 0xBAD2BF4933215152UL,
|
||||
0xE52EDE847038EA23UL, 0xB8A3EFD3D58D7607UL, 0x748472F5AD330239UL,
|
||||
0xCC079CFD428690F6UL, 0x3687450CB7534DACUL, 0x0FEF82D5CC8ACE2AUL,
|
||||
0x214653D5C552CA9AUL, 0x9FCA4E87BF6A04FDUL, 0x78D4B114D234A0D7UL,
|
||||
0x22840422BD6A5BB5UL, 0x5B9ABE0DE1B4410FUL, 0xB3B50007963FDD6BUL,
|
||||
0x53A8A46793B68E35UL, 0x8CDD8E8D188B6033UL, 0x5DD22B6E3ED49572UL,
|
||||
0xE561F5D27F5302D6UL, 0xDF89CEC3322E56CDUL, 0x87167F503D600F90UL,
|
||||
0x1698BB71C8201862UL, 0xF7BF5DFDB023108EUL, 0xA17FB15B66ACFB5FUL,
|
||||
0x2DD771987768073BUL, 0x19299D2D86E0EB29UL, 0x8B537B7F206EED29UL,
|
||||
0xE536DA153325ABFCUL, 0x30A69976796DB3B9UL, 0x8E65A2C94E2D4981UL,
|
||||
0xC301D53553BD6514UL, 0x46DF3639B9E43790UL, 0x3004CD0E5AFD0463UL,
|
||||
0x46E460B0F6ACA1A0UL, 0xCBA210E7372D9BD5UL, 0x45064274A74CA582UL,
|
||||
0xFDD57EA43CE631AEUL, 0xF2BA08FFA4A683D0UL, 0x8DA658C4DAD42999UL,
|
||||
0x7418042943E88040UL, 0x96000F72E9371FEFUL, 0xE9F1212DC8F47302UL,
|
||||
0x2AFB565ECC3553EDUL, 0xCD3D55137EFF7FD6UL, 0xD36F11059388E442UL,
|
||||
0xC4B47515DB5709DDUL, 0x5C363EFBF0BAAB67UL, 0x28C63B5A31650BBBUL,
|
||||
0x6AE54E5068061C81UL, 0xDEE62000F4E0AA21UL, 0xE8238672FE088A8BUL,
|
||||
0x9869CB6370F075B9UL, 0xBA376E2FC7DB330FUL, 0xB0F73E208487CDEEUL,
|
||||
0x359D5017BE37FE97UL, 0x684D828C7F95E2DCUL, 0x9985ECA20E46AE1FUL,
|
||||
0x8030A5137D1A21C4UL, 0xF78CDC00FC37AC39UL, 0x41CDDC8E61D9C644UL,
|
||||
0xB6F3CD1D833BAD1DUL, 0x301D0D858A23DE22UL, 0xA51FCA12AD849BC8UL,
|
||||
0x9F55E615986AB10EUL, 0x904AAA59854F2215UL, 0x12ECEA4AB40F51A7UL,
|
||||
0xB4EDF5807735E23BUL, 0x6190200F1C589478UL, 0xA3CA57F321909A5AUL,
|
||||
0x0BFAEE04B7325B63UL, 0x10C393E7FBCF826DUL, 0x4050A2CA53FDA708UL,
|
||||
0xF31114A9B462B680UL, 0x6FB9A6F121BA2006UL, 0x04550CF09389D602UL,
|
||||
0xB8C7D6D8CA8942F7UL, 0x71BB430C6436E9D1UL, 0xD9070DD5FAA0A10AUL,
|
||||
0x8FD6827757D07E5BUL, 0xD04E6C313F8FD974UL, 0x2CFDEA1187909B9AUL,
|
||||
0xC7A8E758C115F593UL, 0xA79A17663009ACC2UL, 0x8091A6B5372B141DUL,
|
||||
0xEB33B08767F5BA73UL, 0xDAC1F6823B6111C7UL, 0x697DF90C3515611BUL,
|
||||
0xCC1005F198761F48UL, 0x5067E4F5303B45A1UL, 0x04816D292A2D9AC2UL,
|
||||
0x2949C7A0874DD5E9UL, 0x25DB2547804CEE5EUL, 0x7EDC3A8946D6F229UL,
|
||||
0x00B586F67FD0C622UL, 0x3CAE5798E40324E0UL, 0x0A4F1437DE637164UL,
|
||||
0x5F59B2B715871981UL, 0x5D68FF31051E48FBUL, 0x0F2C369D73A2AA46UL,
|
||||
0xB009C6B53DD23399UL, 0xC366A81277084988UL, 0x5AF0E0CA0711E730UL,
|
||||
0x7AD831A9E9E854BAUL, 0x1DD5EDB0CA4E85AEUL, 0x54651209D259E9DDUL,
|
||||
0x3EBB1D9DAB237EADUL, 0xDA96989317AC464CUL, 0xBFCB0F8FBC52C74EUL,
|
||||
0x9597ACB9E27B692EUL, 0x6F436B1643C95B23UL, 0xB81A1253E1C3CD9DUL,
|
||||
0x7B35F37E905EC67EUL, 0x29CE62666EDA76DDUL, 0xFF2490DC1EC4014DUL,
|
||||
0x2D4FF9124DD6B5C4UL, 0xB9510FEC23E0E9D1UL, 0x8BCDBC56541ED071UL,
|
||||
0x5414E097C1B0CCB2UL, 0x82BEF8213076F5C7UL, 0xE9FC9A71BD512615UL,
|
||||
0xCF15ECC39490DF5AUL, 0x49FA9328D8EE97DBUL, 0x5F80FF0153BC2145UL,
|
||||
0xF63BA156B55BCB02UL, 0x0E3B9113109FDF36UL, 0x8FCD6528F54EDE69UL,
|
||||
0x5D6AE9C000054763UL, 0x326D873633431FBBUL, 0x380E07FFCEF7A978UL,
|
||||
0xDCAA09874A1DF230UL, 0x601494F49F6D261EUL, 0x856159486C9B60E3UL,
|
||||
0x85C7F822D07089A5UL, 0xAFFB99CF5AB836C2UL, 0x241AD414FBBB956BUL,
|
||||
0x0CFC042822831692UL, 0x382B16D049727FF2UL, 0x784F9997633C819AUL,
|
||||
0x5C40ED725F6C390AUL, 0x2CE78B7A3331BA9CUL, 0x9C80636639963B41UL,
|
||||
0x1B2D41C968355018UL, 0xD189B57691FB60E4UL, 0x3BD599A9DD85CE31UL,
|
||||
0x46FC8E2EF0B9A77CUL, 0x1A389E07D0075EA4UL, 0x1622CA52401DF2ACUL,
|
||||
0x528F3FF9B7993BFAUL, 0xF16C176CCA292DDBUL, 0x6C154010961EF542UL,
|
||||
0x04B78E92BF6C82DFUL, 0x7D9AFEA6ABB46072UL, 0x3BC573291CBFFC2EUL,
|
||||
0x277FFF096D567AF3UL, 0x1CBEB86841A6F757UL, 0xD0BCD49E76CA20A7UL,
|
||||
0x25B6024756B1FE90UL, 0xE685C04EF84881FBUL, 0xDCAB14B352FC442EUL,
|
||||
0x4FF80A521719953DUL, 0xD10425E411DBE94BUL, 0x60998D0507D6E38DUL,
|
||||
0x146AA432C981BD5EUL, 0x1729A596282AAA41UL, 0x152BE1A263BAF963UL,
|
||||
0x15278DF497D254CAUL, 0xE4B5E9891E88A5DAUL, 0x087FA3472067D0ACUL,
|
||||
0xD99C2899A0AD9158UL, 0x5040F234DC531236UL, 0x9D7E1531259EEE90UL,
|
||||
0x29AFB8B49391036EUL, 0x84B619599642D68EUL, 0xE838AAE0F249545CUL,
|
||||
0x42D524BA8BB96959UL, 0x9A5B3E817A20EE59UL, 0x584F0530EC4C566BUL,
|
||||
0xD6544FD14B47F945UL, 0x3613FB3B553A7CDEUL, 0x284E92B56831AA56UL,
|
||||
0xCEE89BA10E951A22UL, 0x476806FA1A8A44E0UL, 0xC84CEF151885C1DFUL,
|
||||
0x3DB1D5C1B0B73936UL, 0x45D2D90FDF452388UL, 0x038A7DD71BC5DD21UL,
|
||||
0x2AC90C7422C56819UL, 0x4742046638ECE0FBUL, 0x553B44360FC8495DUL,
|
||||
0xC8DBA1CF3F9A6E97UL, 0xF85919F494CAB021UL, 0x1479455C2FF236AFUL,
|
||||
0x29BCAD159F7D018DUL, 0x016DFF51CBA3BCC5UL, 0x234BF8A77F6B1CF5UL,
|
||||
0x20564C6F44F9E641UL, 0x063A550C5AA50FA8UL, 0xB063D0AAAA96DFECUL,
|
||||
0x3EC659DF42C092F8UL, 0x29D4A76A5A5F7E09UL, 0x65EFF3EE6E691D1EUL,
|
||||
0xBD1634F5721CF799UL, 0xE85BD016723B43FFUL, 0x5233E9E7AEA11022UL,
|
||||
0x8C68852EA9039B4CUL, 0x2C978ADBE885BC15UL, 0x726615ED9D497550UL,
|
||||
0x7C1E145EB8D2BD96UL, 0xC2FEFB25935A5D71UL, 0x9EE9C3E1C3DE416FUL,
|
||||
0xFFD568A03E20E0B3UL, 0xF53649AD90156F2AUL, 0x0331B91DCE54E7EDUL,
|
||||
0x67CED5A86E99392FUL, 0x16FC0A5815500B05UL, 0x030392E8D24A7C00UL,
|
||||
0x232E5E31DF32A7B5UL, 0xCC8BF22B1947DF21UL, 0x4EC2C72D9C1EEABDUL,
|
||||
0x0B1B79F45220E668UL, 0xCC3CF0EE9C4A899BUL, 0xFC260A60592EBC80UL,
|
||||
0xC1989A0382CB03EDUL, 0x35FE679A6CD800B2UL, 0x8A6B1ADE4FBB162FUL,
|
||||
0xB0FD284563625295UL, 0xCDCC1C7B2181D024UL, 0x5B8BA0C895C0BB23UL,
|
||||
0xA681FEA9ADCD43DBUL, 0x0FE30FB6876DE718UL, 0x6DDD1E27B769C494UL,
|
||||
0x83A1E58460FFE8BBUL, 0x8FAD6FD2DC90FF65UL, 0x41BB28B81201CB24UL,
|
||||
0xA148CE79B2597204UL, 0x7CB87DF97BB477A6UL, 0x9F79E6DED87DC688UL,
|
||||
0xE044D84A6C758171UL, 0x1A29E750D9EC4097UL, 0x8445FC2B80C4A0F5UL,
|
||||
0x5EFD9784AFED4ED2UL, 0x344C252BD90EB0E4UL, 0xEAD18D2E4418E5B5UL,
|
||||
0x207EF4FFC260BD24UL, 0xD2E5C3AE534EC538UL, 0x2F5A59BF3D10E7E1UL,
|
||||
0x9528E29266C2924CUL, 0x0121B6BDAB45D138UL, 0xADD0256ACBC771DDUL,
|
||||
0x7301769600C6C50DUL, 0x3E7404EA8231D497UL, 0xB39B3840B8D03117UL,
|
||||
0x56EFCEDDEF5B6634UL, 0xE6BE2C0D73B72098UL, 0x5A2841A21A5E4959UL,
|
||||
0xCFEB3586156DF6E0UL, 0xD84F58901E2D65B8UL, 0x79796786CCC59703UL,
|
||||
0x13BFA9A94DD07696UL, 0x7B63116A6B5458B6UL, 0x1406628176C932E0UL,
|
||||
0xDD7ACC4E97F91B1AUL, 0xC82B8F84A56BDBE8UL, 0x325D87D08ED8B0B0UL,
|
||||
0x3F7847B1E82002DDUL, 0x4662900D2ADAF6BFUL, 0x12AE9F58561DB1D7UL,
|
||||
0xA896E956A95CC074UL, 0xAA4FA3A2F8BA4084UL, 0x1D577E35F5DCA67FUL,
|
||||
0x796FF2D75469DEC2UL, 0xBD3F3F87E4DE894EUL, 0x3666B2262DEBFB6BUL,
|
||||
0x1E26D7AEEF976C2EUL, 0x6BC3854F867AC4A0UL, 0x743DBF8C2E95A821UL,
|
||||
0xA62A76B9AE2E645AUL, 0xB4D76561F40187C1UL, 0xD3E5F23F9FA5DB25UL,
|
||||
0x34B1F6B39E6A87E2UL, 0x7DA5C3DFF7BE72CFUL, 0xFDF46B1BE80AD4F9UL,
|
||||
0x0B21121CA9653B8AUL, 0x1199CA9D0A90F21AUL, 0x6021EA302D01E0BAUL,
|
||||
0x8101D063C05CF5D4UL, 0xE2652410DFE78F23UL, 0x84095ACF47C21A25UL,
|
||||
0xD7E29A4DB2FD3A99UL, 0x7793C0CB57959F93UL, 0x94C605308B9E5AA7UL,
|
||||
0x943DB1AC54165B8FUL, 0xC1391A544C07447CUL, 0x3FEF1A61F785D97BUL,
|
||||
0x6DFCC3152478BDE4UL, 0x312AFB0E1982933AUL, 0xB8069C2605631ED3UL,
|
||||
0x5A6076423430BED2UL, 0x34E379F09E2D4F42UL, 0x9167F5E4019573E3UL,
|
||||
0x18F81157828D2A49UL, 0xF4A8723B4955EAB8UL, 0x0BE6C0ABFEA9E8A6UL,
|
||||
0xC63ADCF2CEF25556UL, 0xC5EBD3BEAE9F364FUL, 0xA301D60CF5B6F2FCUL,
|
||||
0x8C606CA881D27A00UL, 0x826FEE13B554C18AUL, 0x8DF251716F10B776UL,
|
||||
0xB2573A33AC7D94FFUL, 0xC0E771248CB7ABB9UL, 0x753DD605DB38F4EAUL,
|
||||
0x21901664C3D92114UL, 0xA408FCB7A1892612UL, 0x3084FC64A03D6722UL,
|
||||
0xC8C9D9569AD42A34UL, 0x1FBFBAFC1694B383UL, 0x1894280CC3F94ABEUL,
|
||||
0xE14C38A7BBB54651UL, 0x23A48CC84A6EB704UL, 0xD034ADC45AABEDBDUL,
|
||||
0xC93F2C21C973C766UL, 0x66A8AEC11D743CC6UL, 0xB4F72AA52E37C145UL,
|
||||
0xB02834DF0D9266B4UL, 0xDB8E724EA1FF402FUL, 0x531E9C058112E352UL,
|
||||
0xC2F692531DB317D2UL, 0xEFC9586498D263A7UL, 0x84F2C524D2F3ADB9UL,
|
||||
0xAFAF02C27CF25D08UL, 0x385873595F9CFC09UL, 0x36DDA10D1A152B7AUL,
|
||||
0x9F9B997A0DACFB55UL, 0x10AB5EB5C4714882UL, 0x7BA4E8703E22B7EEUL,
|
||||
0x0A2BFD558607BCC8UL, 0x201D3706F74F8BA1UL, 0x3DBD573B1358F02EUL,
|
||||
0x5B37645FA93BCEBCUL, 0xC0166864BC1A7544UL, 0x45C7AA5559FC65D7UL,
|
||||
0xEFEA04AA83349B78UL, 0x607859194F9E9FD8UL, 0xA6B9AE5B53CF7710UL,
|
||||
0x73B9142ACBC50821UL, 0x8B7D67495887E65CUL, 0x39B6C4FB2B232E56UL,
|
||||
0xD212DB10E31D2A68UL, 0x629AC0A3D263DC6EUL, 0x6BC2E7FF912050BAUL,
|
||||
0xE0AD5A8FDB183F62UL, 0xF05648134F0C6F0FUL, 0x31E146F4AF980FDAUL,
|
||||
0x7FAF0078D84D62CCUL, 0xE13F044C2830D21EUL, 0x49A047AD204B4C4BUL,
|
||||
0xF3AFBE2237351A74UL, 0x32826C9217BB07EDUL, 0xD4C3AEB099319B5CUL,
|
||||
0x49CE5BD05B2B0F61UL, 0x75DD36984DCBD0A2UL, 0x84EC5D7C2F0AAC6CUL,
|
||||
0x8E59CC9B9942EDDFUL, 0x89FF85DCDF9AE895UL, 0x6F9EE0D8D9E8D414UL,
|
||||
0x10E01A59058D3904UL, 0x1DFAF567BFF55D2EUL, 0x8DD6A18C03382CD4UL,
|
||||
0xE12FD89A0CF58553UL, 0xE245DA902C0C4F5CUL, 0x8BE7566B9987520DUL,
|
||||
0x4CA1C0A4B38A3098UL, 0x81E45015BE618A72UL, 0xA80E0344FF27EFDFUL,
|
||||
0xC98DAEC6DC5005BAUL, 0xF56873F3A958AE5EUL, 0xDB88604670C794ACUL,
|
||||
0x4F68E448DDF6535FUL, 0x3443DBF1CA6031A8UL, 0x73DFA5DEEF409A41UL,
|
||||
0xA7C556941F6643B2UL, 0x424BC40D8C83D962UL, 0x6F292A325B99B726UL,
|
||||
0x6EECB1009717D65EUL, 0x899BE4CE7BB2D8EEUL, 0x25285FED3E59781DUL,
|
||||
0x14C5AEDD76E092D3UL, 0x9BB5EE10567640AEUL, 0xCD62A1D43558FD06UL,
|
||||
0x70A7B09FC5F39447UL, 0xF10064AE92EFFB99UL, 0xD55FA1A918A23082UL,
|
||||
0xD03F28AD25C73A78UL, 0x76CFFFEE094D8B0EUL, 0x4FD5A46AD5A4B4CFUL,
|
||||
0x8F3A36F9D7BF87E3UL, 0x64224315210625BEUL, 0x749A131B71B64350UL,
|
||||
0x9034FF9DAC089F48UL, 0xB58D3017E7321217UL, 0x549D818937D5CE90UL,
|
||||
0x903CE1452419E99CUL, 0xFD052F0388DB2E76UL, 0x7390051E3972480EUL,
|
||||
0x5E5F6EC3F27B3679UL, 0x3E3637D4D4EE917DUL, 0x4FE04068CA2A4309UL,
|
||||
0x98C9C17454AAE42DUL, 0x659AE0BDB113BC21UL, 0x4C0BDECB1511AF4CUL,
|
||||
0x17048BFAEAC0006DUL, 0x68F106AADAA64912UL, 0x2286234ECEB7EAF0UL,
|
||||
0x350CD42CAF697E51UL, 0x8DCDE6D1FAC19A9FUL, 0xF97E55A245A8A8A2UL,
|
||||
0xAAE86B2092DA90A3UL, 0x5123E878AA8AEF76UL, 0x022B88B9694A55F6UL,
|
||||
0xC4C1A9B1C0221985UL, 0x20056D91DD5E0FFEUL, 0xF5BF61EC225C9843UL,
|
||||
0x1A315A05BDCF4A31UL, 0x5710A21A8DF4F15FUL, 0x99BD1A0AF97AD027UL,
|
||||
0x7602C5997AD4E12CUL
|
||||
};
|
||||
|
||||
public static bool IsPopularPassword(char[] vPassword)
|
||||
{
|
||||
Debug.Assert(PpcTable.Length == (PpcTableSize / 64));
|
||||
|
||||
if(vPassword == null) throw new ArgumentNullException("vPassword");
|
||||
if(vPassword.Length == 0) return false;
|
||||
|
||||
foreach(char ch in vPassword)
|
||||
{
|
||||
if(!IsPopularChar(ch)) return false;
|
||||
}
|
||||
|
||||
byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vPassword);
|
||||
|
||||
int[] vIndices = GetTableIndices(pbUtf8, PpcTableSize);
|
||||
Array.Clear(pbUtf8, 0, pbUtf8.Length);
|
||||
|
||||
foreach(int iIndex in vIndices)
|
||||
{
|
||||
if(!GetTableBit(PpcTable, iIndex)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsPopularChar(char ch)
|
||||
{
|
||||
return (((ch >= 'A') && (ch <= 'Z')) || ((ch >= 'a') && (ch <= 'z')) ||
|
||||
((ch >= '0') && (ch <= '9')) || (ch == '_') || (ch == '!'));
|
||||
}
|
||||
|
||||
private static int[] GetTableIndices(byte[] pbPasswordUtf8, int nTableSize)
|
||||
{
|
||||
Debug.Assert(false, "not yet implemented");
|
||||
return null;
|
||||
#if TODO
|
||||
Debug.Assert((nTableSize >= 2) && (nTableSize <= 0x10000));
|
||||
Debug.Assert((nTableSize % 64) == 0);
|
||||
|
||||
SHA512Managed sha = new SHA512Managed();
|
||||
byte[] pbHash = sha.ComputeHash(pbPasswordUtf8);
|
||||
|
||||
int[] vIndices = new int[pbHash.Length / 2];
|
||||
for(int i = 0; i < vIndices.Length; ++i)
|
||||
vIndices[i] = ((((int)pbHash[i * 2] << 8) |
|
||||
(int)pbHash[i * 2 + 1]) % nTableSize);
|
||||
|
||||
return vIndices;
|
||||
#endif
|
||||
}
|
||||
|
||||
private static bool GetTableBit(ulong[] vTable, int iBit)
|
||||
{
|
||||
return ((vTable[iBit >> 6] & (1UL << (iBit & 0x3F))) != 0UL);
|
||||
}
|
||||
|
||||
#if (DEBUG && !KeePassLibSD && TODO)
|
||||
private static bool SetTableBit(ulong[] vTable, int iBit)
|
||||
{
|
||||
if(GetTableBit(vTable, iBit)) return false;
|
||||
|
||||
vTable[iBit >> 6] = (vTable[iBit >> 6] | (1UL << (iBit & 0x3F)));
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void MakeList()
|
||||
{
|
||||
|
||||
string strData = File.ReadAllText("MostPopularPasswords.txt", StrUtil.Utf8);
|
||||
strData += " ";
|
||||
CharStream cs = new CharStream(strData);
|
||||
|
||||
List<string> vPasswords = new List<string>();
|
||||
StringBuilder sbPassword = new StringBuilder();
|
||||
while(true)
|
||||
{
|
||||
char ch = cs.ReadChar();
|
||||
if(ch == char.MinValue) break;
|
||||
|
||||
if(char.IsWhiteSpace(ch))
|
||||
{
|
||||
string strPassword = sbPassword.ToString();
|
||||
strPassword = strPassword.ToLower();
|
||||
|
||||
if(strPassword.Length > 3)
|
||||
{
|
||||
if(vPasswords.IndexOf(strPassword) < 0)
|
||||
vPasswords.Add(strPassword);
|
||||
}
|
||||
|
||||
sbPassword = new StringBuilder();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(!char.IsControl(ch) && !char.IsHighSurrogate(ch) &&
|
||||
!char.IsLowSurrogate(ch) && !char.IsSurrogate(ch));
|
||||
Debug.Assert(IsPopularChar(ch));
|
||||
sbPassword.Append(ch);
|
||||
}
|
||||
}
|
||||
|
||||
ulong[] vTable = new ulong[PpcTableSize / 64];
|
||||
Array.Clear(vTable, 0, vTable.Length);
|
||||
|
||||
long lBitsInTable = 0;
|
||||
foreach(string strPassword in vPasswords)
|
||||
{
|
||||
byte[] pbUtf8 = StrUtil.Utf8.GetBytes(strPassword);
|
||||
int[] vIndices = GetTableIndices(pbUtf8, PpcTableSize);
|
||||
|
||||
foreach(int i in vIndices)
|
||||
{
|
||||
if(SetTableBit(vTable, i)) ++lBitsInTable;
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("\t\t\t");
|
||||
for(int i = 0; i < vTable.Length; ++i)
|
||||
{
|
||||
if(i > 0)
|
||||
{
|
||||
if((i % 3) == 0)
|
||||
{
|
||||
sb.AppendLine(",");
|
||||
sb.Append("\t\t\t");
|
||||
}
|
||||
else sb.Append(", ");
|
||||
}
|
||||
|
||||
sb.Append("0x");
|
||||
sb.Append(vTable[i].ToString("X16"));
|
||||
sb.Append("UL");
|
||||
}
|
||||
|
||||
sb.AppendLine();
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Bits set: " + lBitsInTable.ToString() + " of " +
|
||||
PpcTableSize.ToString());
|
||||
int cHashFn = GetTableIndices(StrUtil.Utf8.GetBytes("Dummy"), PpcTableSize).Length;
|
||||
sb.AppendLine("Hash functions: " + cHashFn.ToString());
|
||||
double dblPhi = Math.Pow(1.0 - ((double)cHashFn / PpcTableSize),
|
||||
(double)vPasswords.Count);
|
||||
sb.AppendLine("Phi (bits unset ratio) estimation: " +
|
||||
dblPhi.ToString(CultureInfo.InvariantCulture));
|
||||
dblPhi = ((double)(PpcTableSize - lBitsInTable) / (double)PpcTableSize);
|
||||
sb.AppendLine("Exact Phi: " + dblPhi.ToString(CultureInfo.InvariantCulture));
|
||||
sb.AppendLine("False positives ratio: " + Math.Pow(1.0 - dblPhi,
|
||||
(double)cHashFn).ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
File.WriteAllText("Table.txt", sb.ToString());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
145
ModernKeePassLib/Cryptography/QualityEstimation.cs
Normal file
145
ModernKeePassLib/Cryptography/QualityEstimation.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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.Utility;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// A class that offers static functions to estimate the quality of
|
||||
/// passwords.
|
||||
/// </summary>
|
||||
public static class QualityEstimation
|
||||
{
|
||||
private enum CharSpaceBits : uint
|
||||
{
|
||||
Control = 32,
|
||||
Alpha = 26,
|
||||
Number = 10,
|
||||
Special = 33,
|
||||
High = 112
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Estimate the quality of a password.
|
||||
/// </summary>
|
||||
/// <param name="vPasswordChars">Password to check.</param>
|
||||
/// <returns>Estimated bit-strength of the password.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">Thrown if the input
|
||||
/// parameter is <c>null</c>.</exception>
|
||||
public static uint EstimatePasswordBits(char[] vPasswordChars)
|
||||
{
|
||||
Debug.Assert(vPasswordChars != null);
|
||||
if(vPasswordChars == null) throw new ArgumentNullException("vPasswordChars");
|
||||
|
||||
bool bChLower = false, bChUpper = false, bChNumber = false;
|
||||
bool bChSpecial = false, bChHigh = false, bChControl = false;
|
||||
Dictionary<char, uint> vCharCounts = new Dictionary<char, uint>();
|
||||
Dictionary<int, uint> vDifferences = new Dictionary<int, uint>();
|
||||
double dblEffectiveLength = 0.0;
|
||||
|
||||
for(int i = 0; i < vPasswordChars.Length; ++i) // Get character types
|
||||
{
|
||||
char tch = vPasswordChars[i];
|
||||
|
||||
if(tch < ' ') bChControl = true;
|
||||
else if((tch >= 'A') && (tch <= 'Z')) bChUpper = true;
|
||||
else if((tch >= 'a') && (tch <= 'z')) bChLower = true;
|
||||
else if((tch >= '0') && (tch <= '9')) bChNumber = true;
|
||||
else if((tch >= ' ') && (tch <= '/')) bChSpecial = true;
|
||||
else if((tch >= ':') && (tch <= '@')) bChSpecial = true;
|
||||
else if((tch >= '[') && (tch <= '`')) bChSpecial = true;
|
||||
else if((tch >= '{') && (tch <= '~')) bChSpecial = true;
|
||||
else if(tch > '~') bChHigh = true;
|
||||
|
||||
double dblDiffFactor = 1.0;
|
||||
if(i >= 1)
|
||||
{
|
||||
int iDiff = (int)tch - (int)vPasswordChars[i - 1];
|
||||
|
||||
uint uDiffCount;
|
||||
if(vDifferences.TryGetValue(iDiff, out uDiffCount))
|
||||
{
|
||||
++uDiffCount;
|
||||
vDifferences[iDiff] = uDiffCount;
|
||||
dblDiffFactor /= (double)uDiffCount;
|
||||
}
|
||||
else vDifferences.Add(iDiff, 1);
|
||||
}
|
||||
|
||||
uint uCharCount;
|
||||
if(vCharCounts.TryGetValue(tch, out uCharCount))
|
||||
{
|
||||
++uCharCount;
|
||||
vCharCounts[tch] = uCharCount;
|
||||
dblEffectiveLength += dblDiffFactor * (1.0 / (double)uCharCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
vCharCounts.Add(tch, 1);
|
||||
dblEffectiveLength += dblDiffFactor;
|
||||
}
|
||||
}
|
||||
|
||||
uint uCharSpace = 0;
|
||||
if(bChControl) uCharSpace += (uint)CharSpaceBits.Control;
|
||||
if(bChUpper) uCharSpace += (uint)CharSpaceBits.Alpha;
|
||||
if(bChLower) uCharSpace += (uint)CharSpaceBits.Alpha;
|
||||
if(bChNumber) uCharSpace += (uint)CharSpaceBits.Number;
|
||||
if(bChSpecial) uCharSpace += (uint)CharSpaceBits.Special;
|
||||
if(bChHigh) uCharSpace += (uint)CharSpaceBits.High;
|
||||
|
||||
if(uCharSpace == 0) return 0;
|
||||
|
||||
double dblBitsPerChar = Math.Log((double)uCharSpace) / Math.Log(2.0);
|
||||
double dblRating = dblBitsPerChar * dblEffectiveLength;
|
||||
|
||||
#if !KeePassLibSD
|
||||
char[] vLowerCopy = new char[vPasswordChars.Length];
|
||||
for(int ilc = 0; ilc < vLowerCopy.Length; ++ilc)
|
||||
vLowerCopy[ilc] = char.ToLower(vPasswordChars[ilc]);
|
||||
if(PopularPasswords.IsPopularPassword(vLowerCopy)) dblRating /= 8.0;
|
||||
Array.Clear(vLowerCopy, 0, vLowerCopy.Length);
|
||||
#endif
|
||||
|
||||
return (uint)Math.Ceiling(dblRating);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Estimate the quality of a password.
|
||||
/// </summary>
|
||||
/// <param name="pbUnprotectedUtf8">Password to check, UTF-8 encoded.</param>
|
||||
/// <returns>Estimated bit-strength of the password.</returns>
|
||||
public static uint EstimatePasswordBits(byte[] pbUnprotectedUtf8)
|
||||
{
|
||||
if(pbUnprotectedUtf8 == null) { Debug.Assert(false); return 0; }
|
||||
|
||||
char[] vChars = StrUtil.Utf8.GetChars(pbUnprotectedUtf8);
|
||||
uint uResult = EstimatePasswordBits(vChars);
|
||||
Array.Clear(vChars, 0, vChars.Length);
|
||||
|
||||
return uResult;
|
||||
}
|
||||
}
|
||||
}
|
48
ModernKeePassLib/Cryptography/SHA256Managed.cs
Normal file
48
ModernKeePassLib/Cryptography/SHA256Managed.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Security.Cryptography;
|
||||
using Windows.Security.Cryptography.Core;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography
|
||||
{
|
||||
// Singleton adaptor that provides a part of the .net SHA256Managed class
|
||||
|
||||
class SHA256Managed
|
||||
{
|
||||
private static SHA256Managed instance;
|
||||
private static HashAlgorithmProvider m_AlgProv;
|
||||
|
||||
private SHA256Managed()
|
||||
{
|
||||
String strAlgName = "SHA256";
|
||||
m_AlgProv = HashAlgorithmProvider.OpenAlgorithm(strAlgName);
|
||||
m_AlgProv.CreateHash();
|
||||
}
|
||||
|
||||
public static SHA256Managed Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new SHA256Managed();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] ComputeHash(byte[] buffer )
|
||||
{
|
||||
IBuffer input = CryptographicBuffer.CreateFromByteArray( buffer);
|
||||
IBuffer hashBuffer = m_AlgProv.HashData(input);
|
||||
byte[] hash;
|
||||
CryptographicBuffer.CopyToByteArray(hashBuffer, out hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
425
ModernKeePassLib/Cryptography/SelfTest.cs
Normal file
425
ModernKeePassLib/Cryptography/SelfTest.cs
Normal file
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 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.Security;
|
||||
using Windows.Security.Cryptography.Core;
|
||||
|
||||
using ModernKeePassLib.Cryptography.Cipher;
|
||||
using ModernKeePassLib.Utility;
|
||||
using ModernKeePassLib.Resources;
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.Security.Cryptography;
|
||||
|
||||
namespace ModernKeePassLib.Cryptography
|
||||
{
|
||||
/* #pragma warning disable 1591
|
||||
/// <summary>
|
||||
/// Return values of the <c>SelfTest.Perform</c> method.
|
||||
/// </summary>
|
||||
public enum SelfTestResult
|
||||
{
|
||||
Success = 0,
|
||||
RijndaelEcbError = 1,
|
||||
Salsa20Error = 2,
|
||||
NativeKeyTransformationError = 3
|
||||
}
|
||||
#pragma warning restore 1591 */
|
||||
|
||||
/// <summary>
|
||||
/// Class containing self-test methods.
|
||||
/// </summary>
|
||||
public static class SelfTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Perform a self-test.
|
||||
/// </summary>
|
||||
public static void Perform()
|
||||
{
|
||||
TestFipsComplianceProblems(); // Must be the first test
|
||||
|
||||
TestRijndael();
|
||||
TestSalsa20();
|
||||
|
||||
TestNativeKeyTransform();
|
||||
|
||||
TestHmacOtp();
|
||||
|
||||
TestProtectedObjects();
|
||||
TestMemUtil();
|
||||
TestStrUtil();
|
||||
TestUrlUtil();
|
||||
|
||||
Debug.Assert((int)PwIcon.World == 1);
|
||||
Debug.Assert((int)PwIcon.Warning == 2);
|
||||
Debug.Assert((int)PwIcon.BlackBerry == 68);
|
||||
}
|
||||
|
||||
internal static void TestFipsComplianceProblems()
|
||||
{
|
||||
#if !KeePassWinRT
|
||||
try { new RijndaelManaged(); }
|
||||
catch(Exception exAes)
|
||||
{
|
||||
throw new SecurityException("AES/Rijndael: " + exAes.Message);
|
||||
}
|
||||
|
||||
try { new SHA256Managed(); }
|
||||
catch(Exception exSha256)
|
||||
{
|
||||
throw new SecurityException("SHA-256: " + exSha256.Message);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void TestRijndael()
|
||||
{
|
||||
|
||||
// Test vector (official ECB test vector #356)
|
||||
byte[] pbIV = new byte[16];
|
||||
byte[] pbTestKey = new byte[32];
|
||||
byte[] pbTestData = new byte[16];
|
||||
byte[] pbReferenceCT = new byte[16] {
|
||||
0x75, 0xD1, 0x1B, 0x0E, 0x3A, 0x68, 0xC4, 0x22,
|
||||
0x3D, 0x88, 0xDB, 0xF0, 0x17, 0x97, 0x7D, 0xD7 };
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 16; ++i) pbIV[i] = 0;
|
||||
for(i = 0; i < 32; ++i) pbTestKey[i] = 0;
|
||||
for(i = 0; i < 16; ++i) pbTestData[i] = 0;
|
||||
pbTestData[0] = 0x04;
|
||||
|
||||
String strAlgName = "AES_ECB"; // Algorithm name
|
||||
|
||||
IBuffer iv = null; // no IV used in ECB.
|
||||
IBuffer buffMsg = CryptographicBuffer.CreateFromByteArray(pbTestData);
|
||||
IBuffer keyMaterial = CryptographicBuffer.CreateFromByteArray(pbTestKey);
|
||||
SymmetricKeyAlgorithmProvider objAlg = SymmetricKeyAlgorithmProvider.OpenAlgorithm(strAlgName);
|
||||
CryptographicKey key = objAlg.CreateSymmetricKey(keyMaterial);
|
||||
|
||||
// Encrypt the data and return.
|
||||
IBuffer buffEncrypt = CryptographicEngine.Encrypt(key, buffMsg, iv);
|
||||
CryptographicBuffer.CopyToByteArray(buffEncrypt, out pbTestData);
|
||||
|
||||
if (!MemUtil.ArraysEqual(pbTestData, pbReferenceCT))
|
||||
throw new SecurityException(KLRes.EncAlgorithmAes + ".");
|
||||
|
||||
|
||||
#if false
|
||||
|
||||
RijndaelManaged r = new RijndaelManaged();
|
||||
|
||||
if(r.BlockSize != 128) // AES block size
|
||||
{
|
||||
Debug.Assert(false);
|
||||
r.BlockSize = 128;
|
||||
}
|
||||
|
||||
r.IV = pbIV;
|
||||
r.KeySize = 256;
|
||||
r.Key = pbTestKey;
|
||||
r.Mode = CipherMode.ECB;
|
||||
ICryptoTransform iCrypt = r.CreateEncryptor();
|
||||
|
||||
iCrypt.TransformBlock(pbTestData, 0, 16, pbTestData, 0);
|
||||
|
||||
if(!MemUtil.ArraysEqual(pbTestData, pbReferenceCT))
|
||||
throw new SecurityException(KLRes.EncAlgorithmAes + ".");
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void TestSalsa20()
|
||||
{
|
||||
// Test values from official set 6, vector 3
|
||||
byte[] pbKey= new byte[32] {
|
||||
0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54,
|
||||
0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC,
|
||||
0x3F, 0x92, 0xE5, 0x38, 0x8B, 0xDE, 0x31, 0x84,
|
||||
0xD7, 0x2A, 0x7D, 0xD0, 0x23, 0x76, 0xC9, 0x1C
|
||||
};
|
||||
byte[] pbIV = new byte[8] { 0x28, 0x8F, 0xF6, 0x5D,
|
||||
0xC4, 0x2B, 0x92, 0xF9 };
|
||||
byte[] pbExpected = new byte[16] {
|
||||
0x5E, 0x5E, 0x71, 0xF9, 0x01, 0x99, 0x34, 0x03,
|
||||
0x04, 0xAB, 0xB2, 0x2A, 0x37, 0xB6, 0x62, 0x5B
|
||||
};
|
||||
|
||||
byte[] pb = new byte[16];
|
||||
Salsa20Cipher c = new Salsa20Cipher(pbKey, pbIV);
|
||||
c.Encrypt(pb, pb.Length, false);
|
||||
if(!MemUtil.ArraysEqual(pb, pbExpected))
|
||||
throw new SecurityException("Salsa20.");
|
||||
|
||||
#if DEBUG
|
||||
// Extended test in debug mode
|
||||
byte[] pbExpected2 = new byte[16] {
|
||||
0xAB, 0xF3, 0x9A, 0x21, 0x0E, 0xEE, 0x89, 0x59,
|
||||
0x8B, 0x71, 0x33, 0x37, 0x70, 0x56, 0xC2, 0xFE
|
||||
};
|
||||
byte[] pbExpected3 = new byte[16] {
|
||||
0x1B, 0xA8, 0x9D, 0xBD, 0x3F, 0x98, 0x83, 0x97,
|
||||
0x28, 0xF5, 0x67, 0x91, 0xD5, 0xB7, 0xCE, 0x23
|
||||
};
|
||||
|
||||
Random r = new Random();
|
||||
int nPos = Salsa20ToPos(c, r, pb.Length, 65536);
|
||||
c.Encrypt(pb, pb.Length, false);
|
||||
if(!MemUtil.ArraysEqual(pb, pbExpected2))
|
||||
throw new SecurityException("Salsa20-2.");
|
||||
|
||||
nPos = Salsa20ToPos(c, r, nPos + pb.Length, 131008);
|
||||
Array.Clear(pb, 0, pb.Length);
|
||||
c.Encrypt(pb, pb.Length, true);
|
||||
if(!MemUtil.ArraysEqual(pb, pbExpected3))
|
||||
throw new SecurityException("Salsa20-3.");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
private static int Salsa20ToPos(Salsa20Cipher c, Random r, int nPos,
|
||||
int nTargetPos)
|
||||
{
|
||||
byte[] pb = new byte[512];
|
||||
|
||||
while(nPos < nTargetPos)
|
||||
{
|
||||
int x = r.Next(1, 513);
|
||||
int nGen = Math.Min(nTargetPos - nPos, x);
|
||||
c.Encrypt(pb, nGen, r.Next(0, 2) == 0);
|
||||
nPos += nGen;
|
||||
}
|
||||
|
||||
return nTargetPos;
|
||||
}
|
||||
#endif
|
||||
|
||||
private static void TestNativeKeyTransform()
|
||||
{
|
||||
#if DEBUG && TODO
|
||||
byte[] pbOrgKey = CryptoRandom.Instance.GetRandomBytes(32);
|
||||
byte[] pbSeed = CryptoRandom.Instance.GetRandomBytes(32);
|
||||
ulong uRounds = (ulong)((new Random()).Next(1, 0x3FFF));
|
||||
|
||||
byte[] pbManaged = new byte[32];
|
||||
Array.Copy(pbOrgKey, pbManaged, 32);
|
||||
if(CompositeKey.TransformKeyManaged(pbManaged, pbSeed, uRounds) == false)
|
||||
throw new SecurityException("Managed transform.");
|
||||
|
||||
byte[] pbNative = new byte[32];
|
||||
Array.Copy(pbOrgKey, pbNative, 32);
|
||||
if(NativeLib.TransformKey256(pbNative, pbSeed, uRounds) == false)
|
||||
return; // Native library not available ("success")
|
||||
|
||||
if(!MemUtil.ArraysEqual(pbManaged, pbNative))
|
||||
throw new SecurityException("Native transform.");
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void TestMemUtil()
|
||||
{
|
||||
#if DEBUG && !KeePassWinRT
|
||||
Random r = new Random();
|
||||
byte[] pb = CryptoRandom.Instance.GetRandomBytes((uint)r.Next(
|
||||
0, 0x2FFFF));
|
||||
|
||||
byte[] pbCompressed = MemUtil.Compress(pb);
|
||||
if(!MemUtil.ArraysEqual(MemUtil.Decompress(pbCompressed), pb))
|
||||
throw new InvalidOperationException("GZip");
|
||||
|
||||
pb = Encoding.ASCII.GetBytes("012345678901234567890a");
|
||||
byte[] pbN = Encoding.ASCII.GetBytes("9012");
|
||||
if(MemUtil.IndexOf<byte>(pb, pbN) != 9)
|
||||
throw new InvalidOperationException("MemUtil-1");
|
||||
pbN = Encoding.ASCII.GetBytes("01234567890123");
|
||||
if(MemUtil.IndexOf<byte>(pb, pbN) != 0)
|
||||
throw new InvalidOperationException("MemUtil-2");
|
||||
pbN = Encoding.ASCII.GetBytes("a");
|
||||
if(MemUtil.IndexOf<byte>(pb, pbN) != 21)
|
||||
throw new InvalidOperationException("MemUtil-3");
|
||||
pbN = Encoding.ASCII.GetBytes("0a");
|
||||
if(MemUtil.IndexOf<byte>(pb, pbN) != 20)
|
||||
throw new InvalidOperationException("MemUtil-4");
|
||||
pbN = Encoding.ASCII.GetBytes("1");
|
||||
if(MemUtil.IndexOf<byte>(pb, pbN) != 1)
|
||||
throw new InvalidOperationException("MemUtil-5");
|
||||
pbN = Encoding.ASCII.GetBytes("b");
|
||||
if(MemUtil.IndexOf<byte>(pb, pbN) >= 0)
|
||||
throw new InvalidOperationException("MemUtil-6");
|
||||
pbN = Encoding.ASCII.GetBytes("012b");
|
||||
if(MemUtil.IndexOf<byte>(pb, pbN) >= 0)
|
||||
throw new InvalidOperationException("MemUtil-7");
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void TestHmacOtp()
|
||||
{
|
||||
#if (DEBUG && !KeePassLibSD && TODO)
|
||||
byte[] pbSecret = Encoding.ASCII.GetBytes("12345678901234567890");
|
||||
string[] vExp = new string[]{ "755224", "287082", "359152",
|
||||
"969429", "338314", "254676", "287922", "162583", "399871",
|
||||
"520489" };
|
||||
|
||||
for(int i = 0; i < vExp.Length; ++i)
|
||||
{
|
||||
if(HmacOtp.Generate(pbSecret, (ulong)i, 6, false, -1) != vExp[i])
|
||||
throw new InvalidOperationException("HmacOtp");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void TestProtectedObjects()
|
||||
{
|
||||
|
||||
#if TODO
|
||||
#if DEBUG
|
||||
byte[] pbData = Encoding.UTF8.GetBytes("Test Test Test Test");
|
||||
ProtectedBinary pb = new ProtectedBinary(true, pbData);
|
||||
if(!pb.IsProtected) throw new SecurityException("ProtectedBinary-1");
|
||||
|
||||
byte[] pbDec = pb.ReadData();
|
||||
if(!MemUtil.ArraysEqual(pbData, pbDec))
|
||||
throw new SecurityException("ProtectedBinary-2");
|
||||
if(!pb.IsProtected) throw new SecurityException("ProtectedBinary-3");
|
||||
|
||||
byte[] pbData2 = Encoding.UTF8.GetBytes("Test Test Test Test");
|
||||
byte[] pbData3 = Encoding.UTF8.GetBytes("Test Test Test Test Test");
|
||||
ProtectedBinary pb2 = new ProtectedBinary(true, pbData2);
|
||||
ProtectedBinary pb3 = new ProtectedBinary(true, pbData3);
|
||||
if(!pb.Equals(pb2)) throw new SecurityException("ProtectedBinary-4");
|
||||
if(pb.Equals(pb3)) throw new SecurityException("ProtectedBinary-5");
|
||||
if(pb2.Equals(pb3)) throw new SecurityException("ProtectedBinary-6");
|
||||
|
||||
if(pb.GetHashCode() != pb2.GetHashCode())
|
||||
throw new SecurityException("ProtectedBinary-7");
|
||||
if(!((object)pb).Equals((object)pb2))
|
||||
throw new SecurityException("ProtectedBinary-8");
|
||||
if(((object)pb).Equals((object)pb3))
|
||||
throw new SecurityException("ProtectedBinary-9");
|
||||
if(((object)pb2).Equals((object)pb3))
|
||||
throw new SecurityException("ProtectedBinary-10");
|
||||
|
||||
ProtectedString ps = new ProtectedString();
|
||||
if(ps.Length != 0) throw new SecurityException("ProtectedString-1");
|
||||
if(!ps.IsEmpty) throw new SecurityException("ProtectedString-2");
|
||||
if(ps.ReadString().Length != 0)
|
||||
throw new SecurityException("ProtectedString-3");
|
||||
|
||||
ps = new ProtectedString(true, "Test");
|
||||
ProtectedString ps2 = new ProtectedString(true,
|
||||
StrUtil.Utf8.GetBytes("Test"));
|
||||
if(ps.IsEmpty) throw new SecurityException("ProtectedString-4");
|
||||
pbData = ps.ReadUtf8();
|
||||
pbData2 = ps2.ReadUtf8();
|
||||
if(!MemUtil.ArraysEqual(pbData, pbData2))
|
||||
throw new SecurityException("ProtectedString-5");
|
||||
if(pbData.Length != 4)
|
||||
throw new SecurityException("ProtectedString-6");
|
||||
if(ps.ReadString() != ps2.ReadString())
|
||||
throw new SecurityException("ProtectedString-7");
|
||||
pbData = ps.ReadUtf8();
|
||||
pbData2 = ps2.ReadUtf8();
|
||||
if(!MemUtil.ArraysEqual(pbData, pbData2))
|
||||
throw new SecurityException("ProtectedString-8");
|
||||
if(!ps.IsProtected) throw new SecurityException("ProtectedString-9");
|
||||
if(!ps2.IsProtected) throw new SecurityException("ProtectedString-10");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void TestStrUtil()
|
||||
{
|
||||
#if DEBUG
|
||||
string[] vSeps = new string[]{ "ax", "b", "c" };
|
||||
const string str1 = "axbqrstcdeax";
|
||||
List<string> v1 = StrUtil.SplitWithSep(str1, vSeps, true);
|
||||
|
||||
if(v1.Count != 9) throw new InvalidOperationException("StrUtil-1");
|
||||
if(v1[0].Length > 0) throw new InvalidOperationException("StrUtil-2");
|
||||
if(!v1[1].Equals("ax")) throw new InvalidOperationException("StrUtil-3");
|
||||
if(v1[2].Length > 0) throw new InvalidOperationException("StrUtil-4");
|
||||
if(!v1[3].Equals("b")) throw new InvalidOperationException("StrUtil-5");
|
||||
if(!v1[4].Equals("qrst")) throw new InvalidOperationException("StrUtil-6");
|
||||
if(!v1[5].Equals("c")) throw new InvalidOperationException("StrUtil-7");
|
||||
if(!v1[6].Equals("de")) throw new InvalidOperationException("StrUtil-8");
|
||||
if(!v1[7].Equals("ax")) throw new InvalidOperationException("StrUtil-9");
|
||||
if(v1[8].Length > 0) throw new InvalidOperationException("StrUtil-10");
|
||||
|
||||
const string str2 = "12ab56";
|
||||
List<string> v2 = StrUtil.SplitWithSep(str2, new string[]{ "AB" }, false);
|
||||
if(v2.Count != 3) throw new InvalidOperationException("StrUtil-11");
|
||||
if(!v2[0].Equals("12")) throw new InvalidOperationException("StrUtil-12");
|
||||
if(!v2[1].Equals("AB")) throw new InvalidOperationException("StrUtil-13");
|
||||
if(!v2[2].Equals("56")) throw new InvalidOperationException("StrUtil-14");
|
||||
|
||||
List<string> v3 = StrUtil.SplitWithSep("pqrs", vSeps, false);
|
||||
if(v3.Count != 1) throw new InvalidOperationException("StrUtil-15");
|
||||
if(!v3[0].Equals("pqrs")) throw new InvalidOperationException("StrUtil-16");
|
||||
|
||||
if(StrUtil.VersionToString(0x000F000E000D000CUL) != "15.14.13.12")
|
||||
throw new InvalidOperationException("StrUtil-V1");
|
||||
if(StrUtil.VersionToString(0x00FF000E00010000UL) != "255.14.1")
|
||||
throw new InvalidOperationException("StrUtil-V2");
|
||||
if(StrUtil.VersionToString(0x000F00FF00000000UL) != "15.255")
|
||||
throw new InvalidOperationException("StrUtil-V3");
|
||||
if(StrUtil.VersionToString(0x00FF000000000000UL) != "255")
|
||||
throw new InvalidOperationException("StrUtil-V4");
|
||||
if(StrUtil.VersionToString(0x00FF000000000000UL, true) != "255.0")
|
||||
throw new InvalidOperationException("StrUtil-V5");
|
||||
if(StrUtil.VersionToString(0x0000000000070000UL, true) != "0.0.7")
|
||||
throw new InvalidOperationException("StrUtil-V6");
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void TestUrlUtil()
|
||||
{
|
||||
#if DEBUG && TODO
|
||||
if(UrlUtil.GetHost(@"scheme://domain:port/path?query_string#fragment_id") !=
|
||||
"domain")
|
||||
throw new InvalidOperationException("UrlUtil-H1");
|
||||
if(UrlUtil.GetHost(@"http://example.org:80") != "example.org")
|
||||
throw new InvalidOperationException("UrlUtil-H2");
|
||||
if(UrlUtil.GetHost(@"mailto:bob@example.com") != "example.com")
|
||||
throw new InvalidOperationException("UrlUtil-H3");
|
||||
if(UrlUtil.GetHost(@"ftp://asmith@ftp.example.org") != "ftp.example.org")
|
||||
throw new InvalidOperationException("UrlUtil-H4");
|
||||
if(UrlUtil.GetHost(@"scheme://username:password@domain:port/path?query_string#fragment_id") !=
|
||||
"domain")
|
||||
throw new InvalidOperationException("UrlUtil-H5");
|
||||
if(UrlUtil.GetHost(@"bob@example.com") != "example.com")
|
||||
throw new InvalidOperationException("UrlUtil-H6");
|
||||
if(UrlUtil.GetHost(@"s://u:p@d.tld:p/p?q#f") != "d.tld")
|
||||
throw new InvalidOperationException("UrlUtil-H7");
|
||||
|
||||
if(NativeLib.IsUnix()) return;
|
||||
|
||||
string strBase = "\\\\HOMESERVER\\Apps\\KeePass\\KeePass.exe";
|
||||
string strDoc = "\\\\HOMESERVER\\Documents\\KeePass\\NewDatabase.kdbx";
|
||||
string strRel = "..\\..\\Documents\\KeePass\\NewDatabase.kdbx";
|
||||
|
||||
string str = UrlUtil.MakeRelativePath(strBase, strDoc);
|
||||
if(!str.Equals(strRel)) throw new InvalidOperationException("UrlUtil-R1");
|
||||
|
||||
str = UrlUtil.MakeAbsolutePath(strBase, strRel);
|
||||
if(!str.Equals(strDoc)) throw new InvalidOperationException("UrlUtil-R2");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user