ModernKeePassLib custom PCL version

This commit is contained in:
2017-09-22 15:40:24 +02:00
parent baba70e56d
commit a43bc20eb3
98 changed files with 6049 additions and 3038 deletions

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2014 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
@@ -18,26 +18,37 @@
*/
using System;
using System.Security;
#if PCL
using Windows.Security.Cryptography;
//using System.Windows.Forms;
//using System.Drawing;
#else
using System.Security.Cryptography;
#endif
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.Core;
using ModernKeePassLib.Utility;
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
/// <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 byte[] m_pbEntropyPool = new byte[64];
private uint m_uCounter;
#if PCL
//private IRandomNumberGenerator m_rng = NetFxCrypto.RandomNumberGenerator;
#else
private RNGCryptoServiceProvider m_rng = new RNGCryptoServiceProvider();
#endif
private ulong m_uGeneratedBytesCount = 0;
// private object m_oSyncRoot = new object();
private object m_oSyncRoot = new object();
private static CryptoRandom m_pInstance = null;
public static CryptoRandom Instance
@@ -51,44 +62,7 @@ namespace ModernKeePassLib.Cryptography
}
}
#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.
@@ -126,19 +100,25 @@ namespace ModernKeePassLib.Cryptography
/// <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
#if PCL
var shaNew = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512);
pbNewData = shaNew.HashData(pbEntropy.AsBuffer()).ToArray();
#else
#if !KeePassLibSD
SHA512Managed shaNew = new SHA512Managed();
#else
SHA256Managed shaNew = new SHA256Managed();
#endif
pbNewData = shaNew.ComputeHash(pbEntropy);
#endif
}
MemoryStream ms = new MemoryStream();
@@ -148,6 +128,11 @@ namespace ModernKeePassLib.Cryptography
ms.Write(pbNewData, 0, pbNewData.Length);
byte[] pbFinal = ms.ToArray();
#if PCL
var shaPool = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512);
m_pbEntropyPool = shaPool.HashData(pbFinal.AsBuffer()).ToArray();
#else
#if !KeePassLibSD
Debug.Assert(pbFinal.Length == (64 + pbNewData.Length));
SHA512Managed shaPool = new SHA512Managed();
@@ -155,16 +140,14 @@ namespace ModernKeePassLib.Cryptography
SHA256Managed shaPool = new SHA256Managed();
#endif
m_pbEntropyPool = shaPool.ComputeHash(pbFinal);
#endif
}
ms.Close();
ms.Dispose();
}
private static byte[] GetSystemData(Random rWeak)
{
MemoryStream ms = new MemoryStream();
byte[] pb;
@@ -174,21 +157,36 @@ namespace ModernKeePassLib.Cryptography
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);
#if (!PCL && !KeePassLibSD && !KeePassRT)
// In try-catch for systems without GUI;
// https://sourceforge.net/p/keepass/discussion/329221/thread/20335b73/
try
{
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);
}
catch(Exception) { }
#endif
pb = MemUtil.UInt32ToBytes((uint)rWeak.Next());
ms.Write(pb, 0, pb.Length);
pb = MemUtil.UInt32ToBytes((uint)NativeLib.GetPlatformID());
#if PCL
pb = MemUtil.UInt32ToBytes((uint)Environment.ProcessorCount);
ms.Write(pb, 0, pb.Length);
#if !KeePassLibSD
pb = MemUtil.UInt32ToBytes((uint)Environment.CurrentManagedThreadId);
ms.Write(pb, 0, pb.Length);
#else
pb = MemUtil.UInt32ToBytes((uint)NativeLib.GetPlatformID());
ms.Write(pb, 0, pb.Length);
#endif
#if (!PCL && !KeePassLibSD && !KeePassRT)
Process p = null;
try
{
pb = MemUtil.UInt32ToBytes((uint)Environment.ProcessorCount);
@@ -197,13 +195,11 @@ namespace ModernKeePassLib.Cryptography
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);
pb = MemUtil.UInt32ToBytes((uint)v.GetHashCode());
ms.Write(pb, 0, pb.Length);
Process p = Process.GetCurrentProcess();
p = Process.GetCurrentProcess();
pb = MemUtil.UInt64ToBytes((ulong)p.Handle.ToInt64());
ms.Write(pb, 0, pb.Length);
pb = MemUtil.UInt32ToBytes((uint)p.HandleCount);
@@ -236,33 +232,31 @@ namespace ModernKeePassLib.Cryptography
// ms.Write(pb, 0, pb.Length);
}
catch(Exception) { }
finally
{
try { if(p != null) p.Dispose(); }
catch(Exception) { Debug.Assert(false); }
}
#endif
pb = Guid.NewGuid().ToByteArray();
ms.Write(pb, 0, pb.Length);
byte[] pbAll = ms.ToArray();
ms.Close();
ms.Dispose();
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);
//byte[] pbCspRandom = new byte[32];
var pbCspRandom = CryptographicBuffer.GenerateRandom(32);
//m_rng.GetBytes(pbCspRandom);
return pbCspRandom;
return pbCspRandom.ToArray();
}
private byte[] GenerateRandom256()
{
if(this.GenerateRandom256Pre != null)
this.GenerateRandom256Pre(this, EventArgs.Empty);
@@ -281,16 +275,20 @@ namespace ModernKeePassLib.Cryptography
pbFinal = ms.ToArray();
Debug.Assert(pbFinal.Length == (m_pbEntropyPool.Length +
pbCounter.Length + pbCspRandom.Length));
ms.Close();
ms.Dispose();
m_uGeneratedBytesCount += 32;
}
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
return sha256.HashData(pbFinal.AsBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed();
return sha256.ComputeHash(pbFinal);
#endif
}
/// <summary>
/// Get a number of cryptographically strong random bytes.
/// This method is thread-safe.
@@ -312,7 +310,7 @@ namespace ModernKeePassLib.Cryptography
long lCopy = (long)((uRequestedBytes < 32) ? uRequestedBytes : 32);
#if !KeePassLibSD
#if (!PCL && !KeePassLibSD && !KeePassRT)
Array.Copy(pbRandom256, 0, pbRes, lPos, lCopy);
#else
Array.Copy(pbRandom256, 0, pbRes, (int)lPos, (int)lCopy);
@@ -325,8 +323,5 @@ namespace ModernKeePassLib.Cryptography
Debug.Assert((int)lPos == pbRes.Length);
return pbRes;
}
#endif // !KeePassWinRT
}
}