From a11d2092809ad42fd9b26f1f9a72921839f132f6 Mon Sep 17 00:00:00 2001 From: Geoffroy Bonneville Date: Mon, 23 Oct 2017 10:29:07 +0200 Subject: [PATCH] Correct implementation of SHA512 with WinRT in KeepassLib --- .../Serialization/KdbxFileTests.cs | 28 +++++----- .../Cryptography/Cipher/StandardAesEngine.cs | 52 +++++++++++++++---- ModernKeePassLib/Cryptography/CryptoRandom.cs | 12 ++--- .../Cryptography/CryptoRandomStream.cs | 6 +-- ModernKeePassLib/Cryptography/CryptoUtil.cs | 22 ++++---- ModernKeePassLib/Cryptography/Hash/Blake2b.cs | 12 +++-- .../Cryptography/Hash/DigestManaged.cs | 26 ---------- .../Cryptography/Hash/SHA256Managed.cs | 13 ----- .../Cryptography/Hash/SHA512Managed.cs | 13 ----- .../PasswordGenerator/PwGenerator.cs | 6 +-- ModernKeePassLib/ModernKeePassLib.csproj | 3 -- ModernKeePassLib/ModernKeePassLib.nuspec | 2 +- ModernKeePassLib/Properties/AssemblyInfo.cs | 4 +- .../Serialization/HashedBlockStream.cs | 16 +++--- ModernKeePassLib/Serialization/KdbxFile.cs | 6 +-- 15 files changed, 101 insertions(+), 120 deletions(-) delete mode 100644 ModernKeePassLib/Cryptography/Hash/DigestManaged.cs delete mode 100644 ModernKeePassLib/Cryptography/Hash/SHA256Managed.cs delete mode 100644 ModernKeePassLib/Cryptography/Hash/SHA512Managed.cs diff --git a/ModernKeePassLib.Test/Serialization/KdbxFileTests.cs b/ModernKeePassLib.Test/Serialization/KdbxFileTests.cs index 18d4bf9..2cd995e 100644 --- a/ModernKeePassLib.Test/Serialization/KdbxFileTests.cs +++ b/ModernKeePassLib.Test/Serialization/KdbxFileTests.cs @@ -1,6 +1,7 @@ using NUnit.Framework; using System; using System.Drawing; +using System.Globalization; using System.IO; using System.Text; using System.Text.RegularExpressions; @@ -40,15 +41,15 @@ namespace ModernKeePassLib.Test.Shared.Serialization "\t\r\n" + "\t\t" + testLocalizedAppName + "\r\n" + "\t\t" + testDatabaseName + "\r\n" + - "\t\t2015-03-14T03:15:26Z\r\n" + + "\t\t2017-10-23T08:03:55Z\r\n" + "\t\t" + testDatabaseDescription + "\r\n" + - "\t\t2015-03-14T03:15:26Z\r\n" + + "\t\t2017-10-23T08:03:55Z\r\n" + "\t\t" + testDefaultUserName + "\r\n" + - "\t\t2015-03-14T03:15:26Z\r\n" + + "\t\t2017-10-23T08:03:55Z\r\n" + "\t\t365\r\n" + //"\t\t" + testColor + "\r\n" + "\t\t\r\n" + - "\t\t2015-03-14T03:15:26Z\r\n" + + "\t\t2017-10-23T08:03:55Z\r\n" + "\t\t-1\r\n" + "\t\t-1\r\n" + "\t\t\r\n" + @@ -60,9 +61,9 @@ namespace ModernKeePassLib.Test.Shared.Serialization "\t\t\r\n" + "\t\tTrue\r\n" + "\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" + - "\t\t2015-03-14T03:15:26Z\r\n" + + "\t\t2017-10-23T08:03:55Z\r\n" + "\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" + - "\t\t2015-03-14T03:15:26Z\r\n" + + "\t\t2017-10-23T08:03:55Z\r\n" + "\t\t10\r\n" + "\t\t6291456\r\n" + "\t\tAAAAAAAAAAAAAAAAAAAAAA==\r\n" + @@ -77,13 +78,13 @@ namespace ModernKeePassLib.Test.Shared.Serialization "\t\t\t" + testRootGroupNotes + "\r\n" + "\t\t\t49\r\n" + "\t\t\t\r\n" + - "\t\t\t\t2015-03-14T03:15:26Z\r\n" + - "\t\t\t\t2015-03-14T03:15:26Z\r\n" + - "\t\t\t\t2015-03-14T03:15:26Z\r\n" + - "\t\t\t\t2015-03-14T03:15:26Z\r\n" + + "\t\t\t\t2017-10-23T08:03:55Z\r\n" + + "\t\t\t\t2017-10-23T08:03:55Z\r\n" + + "\t\t\t\t2017-10-23T08:03:55Z\r\n" + + "\t\t\t\t2017-10-23T08:03:55Z\r\n" + "\t\t\t\tFalse\r\n" + "\t\t\t\t0\r\n" + - "\t\t\t\t2015-03-14T03:15:26Z\r\n" + + "\t\t\t\t2017-10-23T08:03:55Z\r\n" + "\t\t\t\r\n" + "\t\t\tTrue\r\n" + "\t\t\t" + testRootGroupDefaultAutoTypeSequence + "\r\n" + @@ -95,7 +96,7 @@ namespace ModernKeePassLib.Test.Shared.Serialization "\t\r\n" + ""; - const string testDate = "2015-03-14T03:15:26Z"; + const string testDate = "2017-10-23T08:03:55Z"; [Test()] public void TestLoad() @@ -120,7 +121,8 @@ namespace ModernKeePassLib.Test.Shared.Serialization { var database = new PwDatabase(); database.New(new IOConnectionInfo(), new CompositeKey()); - var date = DateTime.Parse(testDate); + var date = DateTime.Parse(testDate, CultureInfo.CurrentCulture, DateTimeStyles.AdjustToUniversal); + //var date = DateTime.UtcNow; PwDatabase.LocalizedAppName = testLocalizedAppName; database.Name = testDatabaseName; database.NameChanged = date; diff --git a/ModernKeePassLib/Cryptography/Cipher/StandardAesEngine.cs b/ModernKeePassLib/Cryptography/Cipher/StandardAesEngine.cs index ad635b2..f2264ce 100644 --- a/ModernKeePassLib/Cryptography/Cipher/StandardAesEngine.cs +++ b/ModernKeePassLib/Cryptography/Cipher/StandardAesEngine.cs @@ -39,6 +39,11 @@ namespace ModernKeePassLib.Cryptography.Cipher /// public sealed class StandardAesEngine : ICipherEngine { +#if !ModernKeePassLib && !KeePassUAP + private const CipherMode m_rCipherMode = CipherMode.CBC; + private const PaddingMode m_rCipherPadding = PaddingMode.PKCS7; +#endif + private static PwUuid g_uuidAes = null; /// @@ -115,18 +120,43 @@ namespace ModernKeePassLib.Cryptography.Cipher byte[] pbLocalKey = new byte[32]; Array.Copy(pbKey, pbLocalKey, 32); - AesEngine aes = new AesEngine(); - CbcBlockCipher cbc = new CbcBlockCipher(aes); - PaddedBufferedBlockCipher bc = new PaddedBufferedBlockCipher(cbc, - new Pkcs7Padding()); - KeyParameter kp = new KeyParameter(pbLocalKey); - ParametersWithIV prmIV = new ParametersWithIV(kp, pbLocalIV); - bc.Init(bEncrypt, prmIV); - IBufferedCipher cpRead = (bEncrypt ? null : bc); - IBufferedCipher cpWrite = (bEncrypt ? bc : null); - return new CipherStream(s, cpRead, cpWrite); - } +#if ModernKeePassLib + AesEngine aes = new AesEngine(); + CbcBlockCipher cbc = new CbcBlockCipher(aes); + PaddedBufferedBlockCipher bc = new PaddedBufferedBlockCipher(cbc, + new Pkcs7Padding()); + KeyParameter kp = new KeyParameter(pbLocalKey); + ParametersWithIV prmIV = new ParametersWithIV(kp, pbLocalIV); + bc.Init(bEncrypt, prmIV); + + IBufferedCipher cpRead = (bEncrypt ? null : bc); + IBufferedCipher cpWrite = (bEncrypt ? bc : null); + return new CipherStream(s, cpRead, cpWrite); +#elif KeePassUAP + return StandardAesEngineExt.CreateStream(s, bEncrypt, pbLocalKey, pbLocalIV); +#else + SymmetricAlgorithm a = CryptoUtil.CreateAes(); + if(a.BlockSize != 128) // AES block size + { + Debug.Assert(false); + a.BlockSize = 128; + } + + a.IV = pbLocalIV; + a.KeySize = 256; + a.Key = pbLocalKey; + a.Mode = m_rCipherMode; + a.Padding = m_rCipherPadding; + + ICryptoTransform iTransform = (bEncrypt ? a.CreateEncryptor() : a.CreateDecryptor()); + Debug.Assert(iTransform != null); + if(iTransform == null) throw new SecurityException("Unable to create AES transform!"); + + return new CryptoStream(s, iTransform, bEncrypt ? CryptoStreamMode.Write : + CryptoStreamMode.Read); +#endif + } public Stream EncryptStream(Stream sPlainText, byte[] pbKey, byte[] pbIV) { diff --git a/ModernKeePassLib/Cryptography/CryptoRandom.cs b/ModernKeePassLib/Cryptography/CryptoRandom.cs index c3888ab..f430d8a 100644 --- a/ModernKeePassLib/Cryptography/CryptoRandom.cs +++ b/ModernKeePassLib/Cryptography/CryptoRandom.cs @@ -120,9 +120,9 @@ namespace ModernKeePassLib.Cryptography { #if ModernKeePassLib - var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); - var buffer = sha256.HashData(CryptographicBuffer.CreateFromByteArray(pbEntropy)); - CryptographicBuffer.CopyToByteArray(buffer, out pbNewData); + var h = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256) + .HashData(CryptographicBuffer.CreateFromByteArray(pbEntropy)); + CryptographicBuffer.CopyToByteArray(h, out pbNewData); #else #if KeePassLibSD using(SHA256Managed shaNew = new SHA256Managed()) @@ -147,9 +147,9 @@ namespace ModernKeePassLib.Cryptography MemUtil.ZeroByteArray(m_pbEntropyPool); #if ModernKeePassLib - var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); - var buffer = sha256.HashData(CryptographicBuffer.CreateFromByteArray(pbCmp)); - CryptographicBuffer.CopyToByteArray(buffer, out m_pbEntropyPool); + var h = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256) + .HashData(CryptographicBuffer.CreateFromByteArray(pbCmp)); + CryptographicBuffer.CopyToByteArray(h, out m_pbEntropyPool); #else #if KeePassLibSD using(SHA256Managed shaPool = new SHA256Managed()) diff --git a/ModernKeePassLib/Cryptography/CryptoRandomStream.cs b/ModernKeePassLib/Cryptography/CryptoRandomStream.cs index 5a6207c..209fa29 100644 --- a/ModernKeePassLib/Cryptography/CryptoRandomStream.cs +++ b/ModernKeePassLib/Cryptography/CryptoRandomStream.cs @@ -98,10 +98,10 @@ namespace ModernKeePassLib.Cryptography byte[] pbKey32 = new byte[32]; byte[] pbIV12 = new byte[12]; #if ModernKeePassLib - var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); - var buffer = sha256.HashData(CryptographicBuffer.CreateFromByteArray(pbKey)); + var h = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512) + .HashData(CryptographicBuffer.CreateFromByteArray(pbKey)); byte[] pbHash; - CryptographicBuffer.CopyToByteArray(buffer, out pbHash); + CryptographicBuffer.CopyToByteArray(h, out pbHash); Array.Copy(pbHash, pbKey32, 32); Array.Copy(pbHash, 32, pbIV12, 0, 12); diff --git a/ModernKeePassLib/Cryptography/CryptoUtil.cs b/ModernKeePassLib/Cryptography/CryptoUtil.cs index 333ec54..02d2415 100644 --- a/ModernKeePassLib/Cryptography/CryptoUtil.cs +++ b/ModernKeePassLib/Cryptography/CryptoUtil.cs @@ -52,15 +52,16 @@ namespace ModernKeePassLib.Cryptography byte[] pbHash; -/*#if ModernKeePassLib - var h = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256).CreateHash(); - CryptographicBuffer.CopyToByteArray(h.GetValueAndReset(), out pbHash); -#else*/ +#if ModernKeePassLib + var h = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256) + .HashData(CryptographicBuffer.CreateFromByteArray(pbData)); + CryptographicBuffer.CopyToByteArray(h, out pbHash); +#else using(SHA256Managed h = new SHA256Managed()) { pbHash = h.ComputeHash(pbData, iOffset, cbCount); } -//#endif +#endif #if DEBUG // Ensure the data has not been modified @@ -90,15 +91,16 @@ namespace ModernKeePassLib.Cryptography if(cbOut <= 32) pbHash = HashSha256(pbIn, iInOffset, cbIn); else { -/*#if ModernKeePassLib - var h = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512).CreateHash(); - CryptographicBuffer.CopyToByteArray(h.GetValueAndReset(), out pbHash); -#else*/ +#if ModernKeePassLib + var h = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512) + .HashData(CryptographicBuffer.CreateFromByteArray(pbIn)); + CryptographicBuffer.CopyToByteArray(h, out pbHash); +#else using(SHA512Managed h = new SHA512Managed()) { pbHash = h.ComputeHash(pbIn, iInOffset, cbIn); } -//#endif +#endif } if(cbOut == pbHash.Length) return pbHash; diff --git a/ModernKeePassLib/Cryptography/Hash/Blake2b.cs b/ModernKeePassLib/Cryptography/Hash/Blake2b.cs index ec14865..a5b1d52 100644 --- a/ModernKeePassLib/Cryptography/Hash/Blake2b.cs +++ b/ModernKeePassLib/Cryptography/Hash/Blake2b.cs @@ -270,11 +270,15 @@ namespace ModernKeePassLib.Cryptography.Hash Reset(); } - internal byte[] ComputeHash(byte[] pbOutBuffer) + internal byte[] ComputeHash(byte[] value) { - byte[] result = new byte[pbOutBuffer.Length]; - DoFinal(result, 0); - return result; + if (value == null) throw new ArgumentNullException(nameof(value)); + + byte[] resBuf = new byte[m_cbHashLength]; + BlockUpdate(value, 0, value.Length); + DoFinal(resBuf, 0); + + return resBuf; } } } diff --git a/ModernKeePassLib/Cryptography/Hash/DigestManaged.cs b/ModernKeePassLib/Cryptography/Hash/DigestManaged.cs deleted file mode 100644 index bfff5dc..0000000 --- a/ModernKeePassLib/Cryptography/Hash/DigestManaged.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using Org.BouncyCastle.Crypto; - -namespace ModernKeePassLib.Cryptography.Hash -{ - public abstract class DigestManaged : IDisposable - { - protected IDigest _hash; - - public byte[] ComputeHash(byte[] value, int offset, int length) - { - if (value == null) throw new ArgumentNullException(nameof(value)); - - byte[] resBuf = new byte[_hash.GetDigestSize()]; - _hash.BlockUpdate(value, offset, length); - _hash.DoFinal(resBuf, 0); - - return resBuf; - } - - public void Dispose() - { - _hash.Reset(); - } - } -} diff --git a/ModernKeePassLib/Cryptography/Hash/SHA256Managed.cs b/ModernKeePassLib/Cryptography/Hash/SHA256Managed.cs deleted file mode 100644 index 1ad2659..0000000 --- a/ModernKeePassLib/Cryptography/Hash/SHA256Managed.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using Org.BouncyCastle.Crypto.Digests; - -namespace ModernKeePassLib.Cryptography.Hash -{ - public class SHA256Managed : DigestManaged - { - public SHA256Managed() - { - _hash = new Sha256Digest(); - } - } -} diff --git a/ModernKeePassLib/Cryptography/Hash/SHA512Managed.cs b/ModernKeePassLib/Cryptography/Hash/SHA512Managed.cs deleted file mode 100644 index e293192..0000000 --- a/ModernKeePassLib/Cryptography/Hash/SHA512Managed.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using Org.BouncyCastle.Crypto.Digests; - -namespace ModernKeePassLib.Cryptography.Hash -{ - public class SHA512Managed : DigestManaged - { - public SHA512Managed() - { - _hash = new Sha512Digest(); - } - } -} diff --git a/ModernKeePassLib/Cryptography/PasswordGenerator/PwGenerator.cs b/ModernKeePassLib/Cryptography/PasswordGenerator/PwGenerator.cs index b915cf4..19c056e 100644 --- a/ModernKeePassLib/Cryptography/PasswordGenerator/PwGenerator.cs +++ b/ModernKeePassLib/Cryptography/PasswordGenerator/PwGenerator.cs @@ -83,10 +83,10 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator if((pbAdditionalEntropy != null) && (pbAdditionalEntropy.Length > 0)) { #if ModernKeePassLib - var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); - var buffer = sha256.HashData(CryptographicBuffer.CreateFromByteArray(pbAdditionalEntropy)); + var h = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512) + .HashData(CryptographicBuffer.CreateFromByteArray(pbAdditionalEntropy)); byte[] pbHash; - CryptographicBuffer.CopyToByteArray(buffer, out pbHash); + CryptographicBuffer.CopyToByteArray(h, out pbHash); MemUtil.XorArray(pbHash, 0, pbKey, 0, pbHash.Length); #else diff --git a/ModernKeePassLib/ModernKeePassLib.csproj b/ModernKeePassLib/ModernKeePassLib.csproj index fbaa27d..4137d30 100644 --- a/ModernKeePassLib/ModernKeePassLib.csproj +++ b/ModernKeePassLib/ModernKeePassLib.csproj @@ -61,10 +61,7 @@ - - - diff --git a/ModernKeePassLib/ModernKeePassLib.nuspec b/ModernKeePassLib/ModernKeePassLib.nuspec index fbe6d49..324a5c1 100644 --- a/ModernKeePassLib/ModernKeePassLib.nuspec +++ b/ModernKeePassLib/ModernKeePassLib.nuspec @@ -2,7 +2,7 @@ ModernKeePassLib - 2.37.1000 + 2.37.2000 ModernKeePassLib Geoffroy Bonneville Geoffroy Bonneville diff --git a/ModernKeePassLib/Properties/AssemblyInfo.cs b/ModernKeePassLib/Properties/AssemblyInfo.cs index 3e24996..adcfd09 100644 --- a/ModernKeePassLib/Properties/AssemblyInfo.cs +++ b/ModernKeePassLib/Properties/AssemblyInfo.cs @@ -40,5 +40,5 @@ using System.Runtime.InteropServices; #endif // Assembly version information -[assembly: AssemblyVersion("2.37.0.1000")] -[assembly: AssemblyFileVersion("2.37.0.1000")] +[assembly: AssemblyVersion("2.37.0.2000")] +[assembly: AssemblyFileVersion("2.37.0.2000")] diff --git a/ModernKeePassLib/Serialization/HashedBlockStream.cs b/ModernKeePassLib/Serialization/HashedBlockStream.cs index 70e568a..847aea8 100644 --- a/ModernKeePassLib/Serialization/HashedBlockStream.cs +++ b/ModernKeePassLib/Serialization/HashedBlockStream.cs @@ -18,20 +18,18 @@ */ using System; -using System.IO; -#if ModernKeePassLib -using System.Linq; -using Windows.Security.Cryptography; -#else -using System.Security.Cryptography; -#endif using System.Diagnostics; +using System.IO; using System.Text; - +#if ModernKeePassLib using ModernKeePassLib.Native; using ModernKeePassLib.Utility; -using Windows.Security.Cryptography.Core; using ModernKeePassLib.Cryptography; +#else +using KeePassLib.Cryptography; +using KeePassLib.Native; +using KeePassLib.Utility; +#endif #if KeePassLibSD using KeePassLibSD; diff --git a/ModernKeePassLib/Serialization/KdbxFile.cs b/ModernKeePassLib/Serialization/KdbxFile.cs index c528c99..0690e5b 100644 --- a/ModernKeePassLib/Serialization/KdbxFile.cs +++ b/ModernKeePassLib/Serialization/KdbxFile.cs @@ -399,9 +399,9 @@ namespace ModernKeePassLib.Serialization pbCmp[64] = 1; #if ModernKeePassLib - var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); - var buffer = sha256.HashData(CryptographicBuffer.CreateFromByteArray(pbCmp)); - CryptographicBuffer.CopyToByteArray(buffer, out pbHmacKey64); + var h = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512) + .HashData(CryptographicBuffer.CreateFromByteArray(pbCmp)); + CryptographicBuffer.CopyToByteArray(h, out pbHmacKey64); #else using(SHA512Managed h = new SHA512Managed()) {