From 1b439a4960114ecc871220e12778241e3e163061 Mon Sep 17 00:00:00 2001 From: Geoffroy Bonneville Date: Thu, 26 Oct 2017 12:38:34 +0200 Subject: [PATCH] ModernKeePassLib implements HMAC correctly Blake2b also implemented, but not tested ModernKeePass app better implements focus on database password box (but still not working correctly) --- .../Controls/OpenDatabaseUserControl.xaml | 14 +- .../Controls/OpenDatabaseUserControl.xaml.cs | 9 - ModernKeePass/ModernKeePass.csproj | 10 +- .../Cryptography/Cipher/ChaCha20Engine.cs | 2 +- .../Cryptography/Cipher/CipherPool.cs | 1 - .../Cryptography/Cipher/StandardAesEngine.cs | 3 + ModernKeePassLib/Cryptography/CryptoRandom.cs | 18 +- ModernKeePassLib/Cryptography/Hash/Blake2b.cs | 304 ++++++++++++------ ModernKeePassLib/Cryptography/Hash/HMAC.cs | 31 ++ .../Cryptography/Hash/HMACSHA1.cs | 15 + .../Cryptography/Hash/HMACSHA256.cs | 39 +-- .../Cryptography/HashingStreamEx.cs | 6 - ModernKeePassLib/Cryptography/HmacOtp.cs | 13 +- .../KeyDerivation/Argon2Kdf.Core.cs | 53 ++- ModernKeePassLib/Keys/KcpKeyFile.cs | 2 +- ModernKeePassLib/Keys/KcpPassword.cs | 2 +- ModernKeePassLib/ModernKeePassLib.csproj | 2 + ModernKeePassLib/ModernKeePassLib.nuspec | 6 +- 18 files changed, 317 insertions(+), 213 deletions(-) create mode 100644 ModernKeePassLib/Cryptography/Hash/HMAC.cs create mode 100644 ModernKeePassLib/Cryptography/Hash/HMACSHA1.cs diff --git a/ModernKeePass/Controls/OpenDatabaseUserControl.xaml b/ModernKeePass/Controls/OpenDatabaseUserControl.xaml index c2ec99d..25a2ce8 100644 --- a/ModernKeePass/Controls/OpenDatabaseUserControl.xaml +++ b/ModernKeePass/Controls/OpenDatabaseUserControl.xaml @@ -4,10 +4,12 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:interactivity="using:Microsoft.Xaml.Interactivity" + xmlns:core="using:Microsoft.Xaml.Interactions.Core" + xmlns:actions="using:ModernKeePass.Actions" mc:Ignorable="d" d:DesignHeight="60" - d:DesignWidth="550" - Loaded="UserControl_Loaded"> + d:DesignWidth="550" > - + + + + + + + diff --git a/ModernKeePass/Controls/OpenDatabaseUserControl.xaml.cs b/ModernKeePass/Controls/OpenDatabaseUserControl.xaml.cs index 4ebfb66..c14b808 100644 --- a/ModernKeePass/Controls/OpenDatabaseUserControl.xaml.cs +++ b/ModernKeePass/Controls/OpenDatabaseUserControl.xaml.cs @@ -1,7 +1,5 @@ using System; -using System.Threading.Tasks; using Windows.System; -using Windows.UI.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Input; using ModernKeePass.Common; @@ -71,12 +69,5 @@ namespace ModernKeePass.Controls StatusTextBlock.Text = string.Empty; } } - - private void UserControl_Loaded(object sender, RoutedEventArgs e) - { - Task.Factory.StartNew( - () => Dispatcher.RunAsync(CoreDispatcherPriority.Low, - () => PasswordBox.Focus(FocusState.Programmatic))); - } } } diff --git a/ModernKeePass/ModernKeePass.csproj b/ModernKeePass/ModernKeePass.csproj index 77c0789..256831f 100644 --- a/ModernKeePass/ModernKeePass.csproj +++ b/ModernKeePass/ModernKeePass.csproj @@ -254,10 +254,6 @@ ..\packages\Microsoft.Toolkit.Uwp.Notifications.2.0.0\lib\dotnet\Microsoft.Toolkit.Uwp.Notifications.dll True - - ..\packages\ModernKeePassLib.2.37.4000\lib\netstandard1.2\ModernKeePassLib.dll - True - ..\packages\Splat.2.0.0\lib\Portable-Win81+Wpa81\Splat.dll True @@ -318,6 +314,12 @@ + + + {2e710089-9559-4967-846c-e763dd1f3acb} + ModernKeePassLib + + 12.0 diff --git a/ModernKeePassLib/Cryptography/Cipher/ChaCha20Engine.cs b/ModernKeePassLib/Cryptography/Cipher/ChaCha20Engine.cs index f22dcf9..7b8a26c 100644 --- a/ModernKeePassLib/Cryptography/Cipher/ChaCha20Engine.cs +++ b/ModernKeePassLib/Cryptography/Cipher/ChaCha20Engine.cs @@ -122,7 +122,7 @@ namespace ModernKeePassLib.Cryptography.Cipher m_c.Dispose(); m_c = null; - //m_sBase.Close(); + m_sBase.Dispose(); m_sBase = null; } diff --git a/ModernKeePassLib/Cryptography/Cipher/CipherPool.cs b/ModernKeePassLib/Cryptography/Cipher/CipherPool.cs index 65323f6..ffe4b1c 100644 --- a/ModernKeePassLib/Cryptography/Cipher/CipherPool.cs +++ b/ModernKeePassLib/Cryptography/Cipher/CipherPool.cs @@ -22,7 +22,6 @@ using System.Collections.Generic; using System.Text; using System.IO; using System.Diagnostics; -using System.Security; namespace ModernKeePassLib.Cryptography.Cipher { diff --git a/ModernKeePassLib/Cryptography/Cipher/StandardAesEngine.cs b/ModernKeePassLib/Cryptography/Cipher/StandardAesEngine.cs index daa4def..b7914f5 100644 --- a/ModernKeePassLib/Cryptography/Cipher/StandardAesEngine.cs +++ b/ModernKeePassLib/Cryptography/Cipher/StandardAesEngine.cs @@ -18,7 +18,10 @@ */ using System; +using System.Collections.Generic; +using System.Text; using System.IO; +using System.Security; using System.Diagnostics; #if ModernKeePassLib using ModernKeePassLib.Resources; diff --git a/ModernKeePassLib/Cryptography/CryptoRandom.cs b/ModernKeePassLib/Cryptography/CryptoRandom.cs index a5d269f..c020acd 100644 --- a/ModernKeePassLib/Cryptography/CryptoRandom.cs +++ b/ModernKeePassLib/Cryptography/CryptoRandom.cs @@ -23,12 +23,12 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; - #if ModernKeePassLib +using ModernKeePassLib.Cryptography.Hash; using Windows.Security.Cryptography; -using Windows.Security.Cryptography.Core; #else using System.Security.Cryptography; +using System.Windows.Forms; #endif using ModernKeePassLib.Native; @@ -120,12 +120,6 @@ namespace ModernKeePassLib.Cryptography byte[] pbNewData = pbEntropy; if(pbEntropy.Length > 64) { -#if ModernKeePassLib - - var h = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256) - .HashData(CryptographicBuffer.CreateFromByteArray(pbEntropy)); - CryptographicBuffer.CopyToByteArray(h, out pbNewData); -#else #if KeePassLibSD using(SHA256Managed shaNew = new SHA256Managed()) #else @@ -134,7 +128,6 @@ namespace ModernKeePassLib.Cryptography { pbNewData = shaNew.ComputeHash(pbEntropy); } -#endif } lock(m_oSyncRoot) @@ -148,11 +141,6 @@ namespace ModernKeePassLib.Cryptography MemUtil.ZeroByteArray(m_pbEntropyPool); -#if ModernKeePassLib - var h = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256) - .HashData(CryptographicBuffer.CreateFromByteArray(pbCmp)); - CryptographicBuffer.CopyToByteArray(h, out m_pbEntropyPool); -#else #if KeePassLibSD using(SHA256Managed shaPool = new SHA256Managed()) #else @@ -161,7 +149,7 @@ namespace ModernKeePassLib.Cryptography { m_pbEntropyPool = shaPool.ComputeHash(pbCmp); } -#endif + MemUtil.ZeroByteArray(pbCmp); } } diff --git a/ModernKeePassLib/Cryptography/Hash/Blake2b.cs b/ModernKeePassLib/Cryptography/Hash/Blake2b.cs index a5b1d52..216b4ff 100644 --- a/ModernKeePassLib/Cryptography/Hash/Blake2b.cs +++ b/ModernKeePassLib/Cryptography/Hash/Blake2b.cs @@ -23,16 +23,26 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Text; +#if ModernKeePassLib +#elif !KeePassUAP +using System.Security.Cryptography; +#endif + using ModernKeePassLib.Utility; -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Tls; namespace ModernKeePassLib.Cryptography.Hash { - public sealed class Blake2b : IDigest + public sealed class Blake2b : IDisposable { + protected int HashSizeValue; + protected internal byte[] HashValue; + protected int State = 0; + + private bool m_bDisposed = false; + private const int NbRounds = 12; private const int NbBlockBytes = 128; private const int NbMaxOutBytes = 64; @@ -70,13 +80,27 @@ namespace ModernKeePassLib.Cryptography.Hash private ulong[] m_m = new ulong[16]; private ulong[] m_v = new ulong[16]; - public string AlgorithmName { get; } = "Blake2b"; - public int HashSize { get; internal set; } + public int HashSize + { + get { return HashSizeValue; } + } - public Blake2b() + public byte[] Hash + { + get + { + if (m_bDisposed) + throw new ObjectDisposedException(null); + if (State != 0) + throw new InvalidOperationException("Blak2B Cryptography Hash Not Yet Finalized"); + return (byte[])HashValue.Clone(); + } + } + + public Blake2b() { m_cbHashLength = NbMaxOutBytes; - this.HashSize = NbMaxOutBytes * 8; // Bits + this.HashSizeValue = NbMaxOutBytes * 8; // Bits Initialize(); } @@ -87,7 +111,7 @@ namespace ModernKeePassLib.Cryptography.Hash throw new ArgumentOutOfRangeException("cbHashLength"); m_cbHashLength = cbHashLength; - this.HashSize = cbHashLength * 8; // Bits + this.HashSizeValue = cbHashLength * 8; // Bits Initialize(); } @@ -166,119 +190,205 @@ namespace ModernKeePassLib.Cryptography.Hash m_t[0] += cb; if(m_t[0] < cb) ++m_t[1]; } - - public int GetDigestSize() - { - return HashSize; - } - public int GetByteLength() - { - return m_buf.Length; - } + private void HashCore(byte[] array, int ibStart, int cbSize) + { + Debug.Assert(m_f[0] == 0); - public void Update(byte input) - { - throw new NotImplementedException(); - } + if((m_cbBuf + cbSize) > NbBlockBytes) // Not '>=' (buffer must not be empty) + { + int cbFill = NbBlockBytes - m_cbBuf; + if(cbFill > 0) Array.Copy(array, ibStart, m_buf, m_cbBuf, cbFill); - public void BlockUpdate(byte[] array, int ibStart, int cbSize) - { - Debug.Assert(m_f[0] == 0); + IncrementCounter((ulong)NbBlockBytes); + Compress(m_buf, 0); - if ((m_cbBuf + cbSize) > NbBlockBytes) // Not '>=' (buffer must not be empty) - { - int cbFill = NbBlockBytes - m_cbBuf; - if (cbFill > 0) Array.Copy(array, ibStart, m_buf, m_cbBuf, cbFill); + m_cbBuf = 0; + cbSize -= cbFill; + ibStart += cbFill; - IncrementCounter((ulong)NbBlockBytes); - Compress(m_buf, 0); + while(cbSize > NbBlockBytes) // Not '>=' (buffer must not be empty) + { + IncrementCounter((ulong)NbBlockBytes); + Compress(array, ibStart); - m_cbBuf = 0; - cbSize -= cbFill; - ibStart += cbFill; + cbSize -= NbBlockBytes; + ibStart += NbBlockBytes; + } + } - while (cbSize > NbBlockBytes) // Not '>=' (buffer must not be empty) - { - IncrementCounter((ulong)NbBlockBytes); - Compress(array, ibStart); + if(cbSize > 0) + { + Debug.Assert((m_cbBuf + cbSize) <= NbBlockBytes); - cbSize -= NbBlockBytes; - ibStart += NbBlockBytes; - } - } + Array.Copy(array, ibStart, m_buf, m_cbBuf, cbSize); + m_cbBuf += cbSize; + } + } - if (cbSize > 0) - { - Debug.Assert((m_cbBuf + cbSize) <= NbBlockBytes); + private byte[] HashFinal() + { + if(m_f[0] != 0) { Debug.Assert(false); throw new InvalidOperationException(); } + Debug.Assert(((m_t[1] == 0) && (m_t[0] == 0)) || + (m_cbBuf > 0)); // Buffer must not be empty for last block processing - Array.Copy(array, ibStart, m_buf, m_cbBuf, cbSize); - m_cbBuf += cbSize; - } - } + m_f[0] = ulong.MaxValue; // Indicate last block - public int DoFinal(byte[] output, int outOff) - { - if (m_f[0] != 0) { Debug.Assert(false); throw new InvalidOperationException(); } - Debug.Assert(((m_t[1] == 0) && (m_t[0] == 0)) || - (m_cbBuf > 0)); // Buffer must not be empty for last block processing + int cbFill = NbBlockBytes - m_cbBuf; + if(cbFill > 0) Array.Clear(m_buf, m_cbBuf, cbFill); - m_f[0] = ulong.MaxValue; // Indicate last block + IncrementCounter((ulong)m_cbBuf); + Compress(m_buf, 0); - int cbFill = NbBlockBytes - m_cbBuf; - if (cbFill > 0) Array.Clear(m_buf, m_cbBuf, cbFill); + byte[] pbHash = new byte[NbMaxOutBytes]; + for(int i = 0; i < m_h.Length; ++i) + MemUtil.UInt64ToBytesEx(m_h[i], pbHash, i << 3); - IncrementCounter((ulong)m_cbBuf); - Compress(m_buf, 0); + if(m_cbHashLength == NbMaxOutBytes) return pbHash; + Debug.Assert(m_cbHashLength < NbMaxOutBytes); - byte[] pbHash = new byte[NbMaxOutBytes]; - for (int i = 0; i < m_h.Length; ++i) - MemUtil.UInt64ToBytesEx(m_h[i], pbHash, i << 3); + byte[] pbShort = new byte[m_cbHashLength]; + if(m_cbHashLength > 0) + Array.Copy(pbHash, pbShort, m_cbHashLength); + MemUtil.ZeroByteArray(pbHash); + return pbShort; + } - if (m_cbHashLength == NbMaxOutBytes) - { - output = pbHash; - return output.Length; - } - Debug.Assert(m_cbHashLength < NbMaxOutBytes); - - byte[] pbShort = new byte[m_cbHashLength]; - if (m_cbHashLength > 0) - Array.Copy(pbHash, pbShort, m_cbHashLength); - MemUtil.ZeroByteArray(pbHash); - output = pbShort; - return output.Length; - } - - public void Reset() - { - MemUtil.ZeroByteArray(m_buf); - } - - public void TransformBlock(byte[] pbBuf, int p1, int pbBufLength, byte[] p3, int p4) + public byte[] ComputeHash(Stream inputStream) { - BlockUpdate(pbBuf, p1, pbBufLength); + if (m_bDisposed) + throw new ObjectDisposedException(null); + + // Default the buffer size to 4K. + byte[] buffer = new byte[4096]; + int bytesRead; + do + { + bytesRead = inputStream.Read(buffer, 0, 4096); + if (bytesRead > 0) + { + HashCore(buffer, 0, bytesRead); + } + } while (bytesRead > 0); + + HashValue = HashFinal(); + byte[] Tmp = (byte[])HashValue.Clone(); + Initialize(); + return (Tmp); } - public void TransformFinalBlock(byte[] emptyByteArray, int i, int i1) + public byte[] ComputeHash(byte[] buffer) { - DoFinal(emptyByteArray, i); + if (m_bDisposed) + throw new ObjectDisposedException(null); + + // Do some validation + if (buffer == null) throw new ArgumentNullException("buffer"); + + HashCore(buffer, 0, buffer.Length); + HashValue = HashFinal(); + byte[] Tmp = (byte[])HashValue.Clone(); + Initialize(); + return (Tmp); + } + + public byte[] ComputeHash(byte[] buffer, int offset, int count) + { + // Do some validation + if (buffer == null) + throw new ArgumentNullException("buffer"); + if (offset < 0) + throw new ArgumentOutOfRangeException("offset", "ArgumentOutOfRange_NeedNonNegNum"); + if (count < 0 || (count > buffer.Length)) + throw new ArgumentException("Argument_InvalidValue"); + if ((buffer.Length - count) < offset) + throw new ArgumentException("Argument_InvalidOffLen"); + + if (m_bDisposed) + throw new ObjectDisposedException(null); + + HashCore(buffer, offset, count); + HashValue = HashFinal(); + byte[] Tmp = (byte[])HashValue.Clone(); + Initialize(); + return (Tmp); + } + + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + // Do some validation, we let BlockCopy do the destination array validation + if (inputBuffer == null) + throw new ArgumentNullException("inputBuffer"); + if (inputOffset < 0) + throw new ArgumentOutOfRangeException("inputOffset", "ArgumentOutOfRange_NeedNonNegNum"); + if (inputCount < 0 || (inputCount > inputBuffer.Length)) + throw new ArgumentException("Argument_InvalidValue"); + if ((inputBuffer.Length - inputCount) < inputOffset) + throw new ArgumentException("Argument_InvalidOffLen"); + + if (m_bDisposed) + throw new ObjectDisposedException(null); + + // Change the State value + State = 1; + HashCore(inputBuffer, inputOffset, inputCount); + if ((outputBuffer != null) && ((inputBuffer != outputBuffer) || (inputOffset != outputOffset))) + Buffer.BlockCopy(inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount); + return inputCount; + } + + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + // Do some validation + if (inputBuffer == null) + throw new ArgumentNullException("inputBuffer"); + if (inputOffset < 0) + throw new ArgumentOutOfRangeException("inputOffset", "ArgumentOutOfRange_NeedNonNegNum"); + if (inputCount < 0 || (inputCount > inputBuffer.Length)) + throw new ArgumentException("Argument_InvalidValue"); + if ((inputBuffer.Length - inputCount) < inputOffset) + throw new ArgumentException("Argument_InvalidOffLen"); + + if (m_bDisposed) + throw new ObjectDisposedException(null); + + HashCore(inputBuffer, inputOffset, inputCount); + HashValue = HashFinal(); + byte[] outputBytes; + if (inputCount != 0) + { + outputBytes = new byte[inputCount]; + Array.Copy(inputBuffer, inputOffset, outputBytes, 0, inputCount); + } + else + { + outputBytes = MemUtil.EmptyByteArray; + } + // reset the State value + State = 0; + return outputBytes; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); } public void Clear() { - Reset(); + (this as IDisposable).Dispose(); } - internal byte[] ComputeHash(byte[] value) - { - if (value == null) throw new ArgumentNullException(nameof(value)); - - byte[] resBuf = new byte[m_cbHashLength]; - BlockUpdate(value, 0, value.Length); - DoFinal(resBuf, 0); - - return resBuf; - } - } + private void Dispose(bool disposing) + { + if (disposing) + { + if (HashValue != null) + Array.Clear(HashValue, 0, HashValue.Length); + HashValue = null; + m_bDisposed = true; + } + } + } } diff --git a/ModernKeePassLib/Cryptography/Hash/HMAC.cs b/ModernKeePassLib/Cryptography/Hash/HMAC.cs new file mode 100644 index 0000000..5e931b4 --- /dev/null +++ b/ModernKeePassLib/Cryptography/Hash/HMAC.cs @@ -0,0 +1,31 @@ +using System; +using Org.BouncyCastle.Crypto.Macs; + +namespace ModernKeePassLib.Cryptography.Hash +{ + public class HMAC : IDisposable + { + protected HMac _hmac; + + public byte[] ComputeHash(byte[] value) + { + return ComputeHash(value, 0, value.Length); + } + + public byte[] ComputeHash(byte[] value, int offset, int length) + { + if (value == null) throw new ArgumentNullException(nameof(value)); + + byte[] resBuf = new byte[_hmac.GetMacSize()]; + _hmac.BlockUpdate(value, 0, length); + _hmac.DoFinal(resBuf, 0); + + return resBuf; + } + + public void Dispose() + { + _hmac.Reset(); + } + } +} diff --git a/ModernKeePassLib/Cryptography/Hash/HMACSHA1.cs b/ModernKeePassLib/Cryptography/Hash/HMACSHA1.cs new file mode 100644 index 0000000..ac298d4 --- /dev/null +++ b/ModernKeePassLib/Cryptography/Hash/HMACSHA1.cs @@ -0,0 +1,15 @@ +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; + +namespace ModernKeePassLib.Cryptography.Hash +{ + public class HMACSHA1: HMAC + { + public HMACSHA1(byte[] key) + { + _hmac = new HMac(new Sha1Digest()); + _hmac.Init(new KeyParameter(key)); + } + } +} diff --git a/ModernKeePassLib/Cryptography/Hash/HMACSHA256.cs b/ModernKeePassLib/Cryptography/Hash/HMACSHA256.cs index 9cc9b9d..65cbaeb 100644 --- a/ModernKeePassLib/Cryptography/Hash/HMACSHA256.cs +++ b/ModernKeePassLib/Cryptography/Hash/HMACSHA256.cs @@ -1,47 +1,18 @@ -using System; -using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Macs; using Org.BouncyCastle.Crypto.Parameters; namespace ModernKeePassLib.Cryptography.Hash { - public class HMACSHA256: IDisposable + public class HMACSHA256: HMAC { - private readonly HMac _hmac; - - public byte[] Hash - { - get - { - byte[] resBuf = new byte[_hmac.GetMacSize()]; - _hmac.DoFinal(resBuf, 0); - return resBuf; - } - } - public HMACSHA256(byte[] key) { _hmac = new HMac(new Sha256Digest()); _hmac.Init(new KeyParameter(key)); } - - public byte[] ComputeHash(byte[] value) - { - if (value == null) throw new ArgumentNullException(nameof(value)); - - byte[] resBuf = new byte[_hmac.GetMacSize()]; - _hmac.BlockUpdate(value, 0, value.Length); - _hmac.DoFinal(resBuf, 0); - - return resBuf; - } - - public void Dispose() - { - _hmac.Reset(); - } - - internal void TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset ) + + /*internal void TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { _hmac.BlockUpdate(inputBuffer, inputOffset, inputCount); } @@ -54,6 +25,6 @@ namespace ModernKeePassLib.Cryptography.Hash internal void Initialize() { _hmac.Reset(); - } + }*/ } } diff --git a/ModernKeePassLib/Cryptography/HashingStreamEx.cs b/ModernKeePassLib/Cryptography/HashingStreamEx.cs index bb1ca6d..8a66e3d 100644 --- a/ModernKeePassLib/Cryptography/HashingStreamEx.cs +++ b/ModernKeePassLib/Cryptography/HashingStreamEx.cs @@ -42,8 +42,6 @@ namespace ModernKeePassLib.Cryptography private readonly Stream m_sBaseStream; private readonly bool m_bWriting; #if ModernKeePassLib - //private ICryptoTransform m_hash; - //private CryptographicHash m_hash; private IDigest m_hash; #else private HashAlgorithm m_hash; @@ -93,8 +91,6 @@ namespace ModernKeePassLib.Cryptography m_sBaseStream = sBaseStream; m_bWriting = bWriting; #if ModernKeePassLib - //m_hash = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(hashAlgorithm ?? HashAlgorithm.Sha256).CreateHash(); - //m_hash = HashAlgorithmProvider.OpenAlgorithm(hashAlgorithm ?? HashAlgorithmNames.Sha256).CreateHash(); m_hash = hashAlgorithm ?? new Sha256Digest(); #elif !KeePassLibSD m_hash = (hashAlgorithm ?? new SHA256Managed()); @@ -128,8 +124,6 @@ namespace ModernKeePassLib.Cryptography try { #if ModernKeePassLib - //m_pbFinalHash = (m_hash as CryptographicHash).GetValueAndReset (); - //CryptographicBuffer.CopyToByteArray(m_hash.GetValueAndReset(), out m_pbFinalHash); m_pbFinalHash = new byte[32]; m_hash.DoFinal(m_pbFinalHash, 0); m_hash.Reset(); diff --git a/ModernKeePassLib/Cryptography/HmacOtp.cs b/ModernKeePassLib/Cryptography/HmacOtp.cs index e35035c..8e8e570 100644 --- a/ModernKeePassLib/Cryptography/HmacOtp.cs +++ b/ModernKeePassLib/Cryptography/HmacOtp.cs @@ -22,8 +22,7 @@ using System.Collections.Generic; using System.Globalization; using System.Text; #if ModernKeePassLib -using Windows.Security.Cryptography; -using Windows.Security.Cryptography.Core; +using ModernKeePassLib.Cryptography.Hash; #elif !KeePassUAP using System.Security.Cryptography; #endif @@ -46,16 +45,10 @@ namespace ModernKeePassLib.Cryptography { byte[] pbText = MemUtil.UInt64ToBytes(uFactor); Array.Reverse(pbText); // To big-endian - -#if ModernKeePassLib - var hsha1 = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha1).CreateHash(CryptographicBuffer.CreateFromByteArray(pbSecret)); - hsha1.Append(CryptographicBuffer.CreateFromByteArray(pbText)); - byte[] pbHash; - CryptographicBuffer.CopyToByteArray(hsha1.GetValueAndReset(), out pbHash); -#else + HMACSHA1 hsha1 = new HMACSHA1(pbSecret); byte[] pbHash = hsha1.ComputeHash(pbText); -#endif + uint uOffset = (uint)(pbHash[pbHash.Length - 1] & 0xF); if((iTruncationOffset >= 0) && (iTruncationOffset < (pbHash.Length - 4))) uOffset = (uint)iTruncationOffset; diff --git a/ModernKeePassLib/Cryptography/KeyDerivation/Argon2Kdf.Core.cs b/ModernKeePassLib/Cryptography/KeyDerivation/Argon2Kdf.Core.cs index 18692c9..1edefa8 100644 --- a/ModernKeePassLib/Cryptography/KeyDerivation/Argon2Kdf.Core.cs +++ b/ModernKeePassLib/Cryptography/KeyDerivation/Argon2Kdf.Core.cs @@ -151,10 +151,8 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation MemUtil.UInt32ToBytesEx((uint)pbAssocData.Length, pbBuf, 0); h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0); h.TransformBlock(pbAssocData, 0, pbAssocData.Length, pbAssocData, 0); - byte[] pbH0 = MemUtil.EmptyByteArray; - h.TransformFinalBlock(pbH0, 0, 0); - /*h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0); - byte[] pbH0 = h.Hash;*/ + h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0); + byte[] pbH0 = h.Hash; Debug.Assert(pbH0.Length == 64); byte[] pbBlockHash = new byte[NbPreHashSeedLength]; @@ -202,9 +200,14 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation // int iSrcOffset = (int)uSrcOffset; // for(int i = 0; i < (int)NbBlockSizeInQW; ++i) // vDst[iDstOffset + i] = vSrc[iSrcOffset + i]; - + +#if ModernKeePassLib || KeePassUAP Array.Copy(vSrc, (int)uSrcOffset, vDst, (int)uDstOffset, (int)NbBlockSizeInQW); +#else + Array.Copy(vSrc, (long)uSrcOffset, vDst, (long)uDstOffset, + (long)NbBlockSizeInQW); +#endif } private static void XorBlock(ulong[] vDst, ulong uDstOffset, ulong[] vSrc, @@ -236,26 +239,23 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation hOut.TransformBlock(pbOutLen, 0, pbOutLen.Length, pbOutLen, 0); hOut.TransformBlock(pbIn, 0, cbIn, pbIn, 0); - hOut.TransformFinalBlock(pbOut, 0, 0); - /*hOut.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0); + hOut.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0); - Array.Copy(hOut.Hash, pbOut, cbOut);*/ + Array.Copy(hOut.Hash, pbOut, cbOut); if(cbOut < 64) hOut.Clear(); return; } - byte[] pbOutBuffer = new byte[64]; h.Initialize(); h.TransformBlock(pbOutLen, 0, pbOutLen.Length, pbOutLen, 0); h.TransformBlock(pbIn, 0, cbIn, pbIn, 0); - h.TransformFinalBlock(pbOutBuffer, 0, 0); + h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0); - /*h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0); + byte[] pbOutBuffer = new byte[64]; + Array.Copy(h.Hash, pbOutBuffer, pbOutBuffer.Length); - Array.Copy(h.Hash, pbOutBuffer, pbOutBuffer.Length);*/ - - int ibOut = 64 / 2; + int ibOut = 64 / 2; Array.Copy(pbOutBuffer, pbOut, ibOut); int cbToProduce = cbOut - ibOut; @@ -272,18 +272,15 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation MemUtil.ZeroByteArray(pbHash); } - /*using(*/ - { - Blake2b hOut = new Blake2b(cbToProduce); /*) - {*/ - byte[] pbHash = hOut.ComputeHash(pbOutBuffer); - Array.Copy(pbHash, 0, pbOut, ibOut, cbToProduce); + using(Blake2b hOut = new Blake2b(cbToProduce)) + { + byte[] pbHash = hOut.ComputeHash(pbOutBuffer); + Array.Copy(pbHash, 0, pbOut, ibOut, cbToProduce); - MemUtil.ZeroByteArray(pbHash); - //} - } + MemUtil.ZeroByteArray(pbHash); + } - MemUtil.ZeroByteArray(pbOutBuffer); + MemUtil.ZeroByteArray(pbOutBuffer); } #if !ARGON2_G_INLINED @@ -468,13 +465,13 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation ti.Pass = r; ti.Lane = (ulong)l; ti.Slice = s; - - /*if(!ThreadPool.QueueUserWorkItem(FillSegmentThr, ti)) +#if !ModernKeePassLib + if(!ThreadPool.QueueUserWorkItem(FillSegmentThr, ti)) { Debug.Assert(false); throw new OutOfMemoryException(); - }*/ - + } +#endif v[l] = ti; } diff --git a/ModernKeePassLib/Keys/KcpKeyFile.cs b/ModernKeePassLib/Keys/KcpKeyFile.cs index 3961b48..d38b6a3 100644 --- a/ModernKeePassLib/Keys/KcpKeyFile.cs +++ b/ModernKeePassLib/Keys/KcpKeyFile.cs @@ -1,6 +1,6 @@ /* KeePass Password Safe - The Open-Source Password Manager - Copyright (C) 2003-2014 Dominik Reichl + Copyright (C) 2003-2017 Dominik Reichl 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 diff --git a/ModernKeePassLib/Keys/KcpPassword.cs b/ModernKeePassLib/Keys/KcpPassword.cs index 5a58c61..e1376f7 100644 --- a/ModernKeePassLib/Keys/KcpPassword.cs +++ b/ModernKeePassLib/Keys/KcpPassword.cs @@ -1,6 +1,6 @@ /* KeePass Password Safe - The Open-Source Password Manager - Copyright (C) 2003-2014 Dominik Reichl + Copyright (C) 2003-2017 Dominik Reichl 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 diff --git a/ModernKeePassLib/ModernKeePassLib.csproj b/ModernKeePassLib/ModernKeePassLib.csproj index d19ee85..73b3b0d 100644 --- a/ModernKeePassLib/ModernKeePassLib.csproj +++ b/ModernKeePassLib/ModernKeePassLib.csproj @@ -62,6 +62,8 @@ + + diff --git a/ModernKeePassLib/ModernKeePassLib.nuspec b/ModernKeePassLib/ModernKeePassLib.nuspec index 233f6c0..099270b 100644 --- a/ModernKeePassLib/ModernKeePassLib.nuspec +++ b/ModernKeePassLib/ModernKeePassLib.nuspec @@ -2,15 +2,15 @@ ModernKeePassLib - 2.37.4000 + 2.37.5000 ModernKeePassLib Geoffroy Bonneville Geoffroy Bonneville https://www.gnu.org/licenses/gpl-3.0.en.html https://github.com/wismna/ModernKeePass false - Portable KeePass Password Management Library that targets .Net Standard and WinRT - Opening and writing back to working order! There is still some untested stuff, mainly related to KDBX file format 4 + Portable KeePass Password Management Library that targets .Net Standard and WinRT. Allows reading, editing and writing to KeePass 2.x databases. + HMAC and Blake2B re-implemented. Copyright © 2017 Geoffroy Bonneville KeePass KeePassLib Portable PCL NetStandard