From eee24819d5faf10ca08ac3fc1332905bd41d47bd Mon Sep 17 00:00:00 2001 From: Philipp Crocoll Date: Mon, 7 Dec 2020 10:43:46 +0100 Subject: [PATCH] add support for Argon2id (see https://github.com/keepassxreboot/keepassxc/issues/4317#issuecomment-738101431) --- .../Cryptography/CryptoRandom.cs | 22 +++ .../Cryptography/CryptoUtil.cs | 151 ++++++++++++++++-- .../KeyDerivation/Argon2Kdf.Core.cs | 81 ++++++++-- .../Cryptography/KeyDerivation/Argon2Kdf.cs | 151 +++++++++++------- .../KeyDerivation/KdfParameters.cs | 2 +- .../Cryptography/KeyDerivation/KdfPool.cs | 7 +- .../KeePassLib2Android.csproj | 1 + 7 files changed, 323 insertions(+), 92 deletions(-) diff --git a/src/KeePassLib2Android/Cryptography/CryptoRandom.cs b/src/KeePassLib2Android/Cryptography/CryptoRandom.cs index 00f1b736..312c71be 100644 --- a/src/KeePassLib2Android/Cryptography/CryptoRandom.cs +++ b/src/KeePassLib2Android/Cryptography/CryptoRandom.cs @@ -367,5 +367,27 @@ namespace KeePassLib.Cryptography Debug.Assert(iPos == pbRes.Length); return pbRes; } + + + private static int g_iWeakSeed = 0; + public static Random NewWeakRandom() + { + long s64 = DateTime.UtcNow.ToBinary(); + int s32 = (int)((s64 >> 32) ^ s64); + + lock (g_oSyncRoot) + { + unchecked + { + g_iWeakSeed += 0x78A8C4B7; // Prime number + s32 ^= g_iWeakSeed; + } + } + + // Prevent overflow in the Random constructor of .NET 2.0 + if (s32 == int.MinValue) s32 = int.MaxValue; + + return new Random(s32); + } } } diff --git a/src/KeePassLib2Android/Cryptography/CryptoUtil.cs b/src/KeePassLib2Android/Cryptography/CryptoUtil.cs index c042080f..6401f0f8 100644 --- a/src/KeePassLib2Android/Cryptography/CryptoUtil.cs +++ b/src/KeePassLib2Android/Cryptography/CryptoUtil.cs @@ -1,6 +1,6 @@ /* KeePass Password Safe - The Open-Source Password Manager - Copyright (C) 2003-2017 Dominik Reichl + Copyright (C) 2003-2020 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 @@ -20,28 +20,67 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; +using System.Reflection; using System.Text; #if !KeePassUAP using System.Security.Cryptography; #endif +using KeePassLib.Native; using KeePassLib.Utility; namespace KeePassLib.Cryptography { public static class CryptoUtil { + private static bool? g_obProtData = null; + public static bool IsProtectedDataSupported + { + get + { + if (g_obProtData.HasValue) return g_obProtData.Value; + + bool b = false; + try + { + Random r = CryptoRandom.NewWeakRandom(); + + byte[] pbData = new byte[137]; + r.NextBytes(pbData); + + byte[] pbEnt = new byte[41]; + r.NextBytes(pbEnt); + + byte[] pbEnc = ProtectedData.Protect(pbData, pbEnt, + DataProtectionScope.CurrentUser); + if ((pbEnc != null) && !MemUtil.ArraysEqual(pbEnc, pbData)) + { + byte[] pbDec = ProtectedData.Unprotect(pbEnc, pbEnt, + DataProtectionScope.CurrentUser); + if ((pbDec != null) && MemUtil.ArraysEqual(pbDec, pbData)) + b = true; + } + } + catch (Exception) { Debug.Assert(false); } + + Debug.Assert(b); // Should be supported on all systems + g_obProtData = b; + return b; + } + } + public static byte[] HashSha256(byte[] pbData) { - if(pbData == null) throw new ArgumentNullException("pbData"); + if (pbData == null) throw new ArgumentNullException("pbData"); return HashSha256(pbData, 0, pbData.Length); } public static byte[] HashSha256(byte[] pbData, int iOffset, int cbCount) { - if(pbData == null) throw new ArgumentNullException("pbData"); + if (pbData == null) throw new ArgumentNullException("pbData"); #if DEBUG byte[] pbCopy = new byte[pbData.Length]; @@ -49,7 +88,7 @@ namespace KeePassLib.Cryptography #endif byte[] pbHash; - using(SHA256Managed h = new SHA256Managed()) + using (SHA256Managed h = new SHA256Managed()) { pbHash = h.ComputeHash(pbData, iOffset, cbCount); } @@ -66,6 +105,22 @@ namespace KeePassLib.Cryptography return pbHash; } + internal static byte[] HashSha256(string strFilePath) + { + byte[] pbHash = null; + + using (FileStream fs = new FileStream(strFilePath, FileMode.Open, + FileAccess.Read, FileShare.Read)) + { + using (SHA256Managed h = new SHA256Managed()) + { + pbHash = h.ComputeHash(fs); + } + } + + return pbHash; + } + /// /// Create a cryptographic key of length /// (in bytes) from . @@ -73,34 +128,34 @@ namespace KeePassLib.Cryptography public static byte[] ResizeKey(byte[] pbIn, int iInOffset, int cbIn, int cbOut) { - if(pbIn == null) throw new ArgumentNullException("pbIn"); - if(cbOut < 0) throw new ArgumentOutOfRangeException("cbOut"); + if (pbIn == null) throw new ArgumentNullException("pbIn"); + if (cbOut < 0) throw new ArgumentOutOfRangeException("cbOut"); - if(cbOut == 0) return MemUtil.EmptyByteArray; + if (cbOut == 0) return MemUtil.EmptyByteArray; byte[] pbHash; - if(cbOut <= 32) pbHash = HashSha256(pbIn, iInOffset, cbIn); + if (cbOut <= 32) pbHash = HashSha256(pbIn, iInOffset, cbIn); else { - using(SHA512Managed h = new SHA512Managed()) + using (SHA512Managed h = new SHA512Managed()) { pbHash = h.ComputeHash(pbIn, iInOffset, cbIn); } } - if(cbOut == pbHash.Length) return pbHash; + if (cbOut == pbHash.Length) return pbHash; byte[] pbRet = new byte[cbOut]; - if(cbOut < pbHash.Length) + if (cbOut < pbHash.Length) Array.Copy(pbHash, pbRet, cbOut); else { int iPos = 0; ulong r = 0; - while(iPos < cbOut) + while (iPos < cbOut) { Debug.Assert(pbHash.Length == 64); - using(HMACSHA256 h = new HMACSHA256(pbHash)) + using (HMACSHA256 h = new HMACSHA256(pbHash)) { byte[] pbR = MemUtil.UInt64ToBytes(r); byte[] pbPart = h.ComputeHash(pbR); @@ -125,5 +180,75 @@ namespace KeePassLib.Cryptography MemUtil.ZeroByteArray(pbHash); return pbRet; } + +#if !KeePassUAP + private static bool? g_obAesCsp = null; + internal static SymmetricAlgorithm CreateAes() + { + if (g_obAesCsp.HasValue) + return (g_obAesCsp.Value ? CreateAesCsp() : new RijndaelManaged()); + + SymmetricAlgorithm a = CreateAesCsp(); + g_obAesCsp = (a != null); + return (a ?? new RijndaelManaged()); + } + + private static SymmetricAlgorithm CreateAesCsp() + { + try + { + // On Windows, the CSP implementation is only minimally + // faster (and for key derivations it's not used anyway, + // as KeePass uses a native implementation based on + // CNG/BCrypt, which is much faster) + if (!NativeLib.IsUnix()) return null; + + string strFqn = Assembly.CreateQualifiedName( + "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", + "System.Security.Cryptography.AesCryptoServiceProvider"); + + Type t = Type.GetType(strFqn); + if (t == null) return null; + + return (Activator.CreateInstance(t) as SymmetricAlgorithm); + } + catch (Exception) { Debug.Assert(false); } + + return null; + } +#endif + + public static byte[] ProtectData(byte[] pb, byte[] pbOptEntropy, + DataProtectionScope s) + { + return ProtectDataPriv(pb, true, pbOptEntropy, s); + } + + public static byte[] UnprotectData(byte[] pb, byte[] pbOptEntropy, + DataProtectionScope s) + { + return ProtectDataPriv(pb, false, pbOptEntropy, s); + } + + private static byte[] ProtectDataPriv(byte[] pb, bool bProtect, + byte[] pbOptEntropy, DataProtectionScope s) + { + if (pb == null) throw new ArgumentNullException("pb"); + + if ((pbOptEntropy != null) && (pbOptEntropy.Length == 0)) + pbOptEntropy = null; + + if (CryptoUtil.IsProtectedDataSupported) + { + if (bProtect) + return ProtectedData.Protect(pb, pbOptEntropy, s); + return ProtectedData.Unprotect(pb, pbOptEntropy, s); + } + + Debug.Assert(false); + byte[] pbCopy = new byte[pb.Length]; + Array.Copy(pb, pbCopy, pb.Length); + return pbCopy; + } } } diff --git a/src/KeePassLib2Android/Cryptography/KeyDerivation/Argon2Kdf.Core.cs b/src/KeePassLib2Android/Cryptography/KeyDerivation/Argon2Kdf.Core.cs index 5813c7c5..bf1dc7a7 100644 --- a/src/KeePassLib2Android/Cryptography/KeyDerivation/Argon2Kdf.Core.cs +++ b/src/KeePassLib2Android/Cryptography/KeyDerivation/Argon2Kdf.Core.cs @@ -46,6 +46,8 @@ namespace KeePassLib.Cryptography.KeyDerivation private const ulong NbBlockSizeInQW = NbBlockSize / 8UL; private const ulong NbSyncPoints = 4; + private const ulong NbAddressesInBlock = 128; + private const int NbPreHashDigestLength = 64; private const int NbPreHashSeedLength = NbPreHashDigestLength + 8; @@ -56,6 +58,7 @@ namespace KeePassLib.Cryptography.KeyDerivation private sealed class Argon2Ctx { + public Argon2Type Type = Argon2Type.D; public uint Version = 0; public ulong Lanes = 0; @@ -89,9 +92,9 @@ namespace KeePassLib.Cryptography.KeyDerivation } } - private static byte[] Argon2d(byte[] pbMsg, byte[] pbSalt, uint uParallel, - ulong uMem, ulong uIt, int cbOut, uint uVersion, byte[] pbSecretKey, - byte[] pbAssocData) + private byte[] Argon2Transform(byte[] pbMsg, byte[] pbSalt, uint uParallel, + ulong uMem, ulong uIt, int cbOut, uint uVersion, byte[] pbSecretKey, + byte[] pbAssocData) { pbSecretKey = (pbSecretKey ?? MemUtil.EmptyByteArray); pbAssocData = (pbAssocData ?? MemUtil.EmptyByteArray); @@ -101,6 +104,7 @@ namespace KeePassLib.Cryptography.KeyDerivation #endif Argon2Ctx ctx = new Argon2Ctx(); + ctx.Type = m_t; ctx.Version = uVersion; ctx.Lanes = uParallel; @@ -137,7 +141,7 @@ namespace KeePassLib.Cryptography.KeyDerivation h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0); MemUtil.UInt32ToBytesEx(uVersion, pbBuf, 0); h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0); - MemUtil.UInt32ToBytesEx(0, pbBuf, 0); // Argon2d type = 0 + MemUtil.UInt32ToBytesEx((uint)m_t, pbBuf, 0); h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0); MemUtil.UInt32ToBytesEx((uint)pbMsg.Length, pbBuf, 0); h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0); @@ -487,18 +491,43 @@ namespace KeePassLib.Cryptography.KeyDerivation private static void FillSegmentThr(object o) { Argon2ThreadInfo ti = (o as Argon2ThreadInfo); - if(ti == null) { Debug.Assert(false); return; } + if (ti == null) { Debug.Assert(false); return; } try { Argon2Ctx ctx = ti.Context; - if(ctx == null) { Debug.Assert(false); return; } + if (ctx == null) { Debug.Assert(false); return; } Debug.Assert(ctx.Version >= MinVersion); bool bCanXor = (ctx.Version >= 0x13U); + ulong[] pbR = new ulong[NbBlockSizeInQW]; + ulong[] pbTmp = new ulong[NbBlockSizeInQW]; + ulong[] pbAddrInputZero = null; + + bool bDataIndependentAddr = ((ctx.Type == Argon2Type.ID) && + (ti.Pass == 0) && (ti.Slice < (NbSyncPoints / 2))); + if (bDataIndependentAddr) + { + pbAddrInputZero = new ulong[NbBlockSizeInQW * 3]; + + const int iInput = (int)NbBlockSizeInQW; + pbAddrInputZero[iInput] = ti.Pass; + pbAddrInputZero[iInput + 1] = ti.Lane; + pbAddrInputZero[iInput + 2] = ti.Slice; + pbAddrInputZero[iInput + 3] = ctx.MemoryBlocks; + pbAddrInputZero[iInput + 4] = ctx.TCost; + pbAddrInputZero[iInput + 5] = (ulong)ctx.Type; + } + ulong uStart = 0; - if((ti.Pass == 0) && (ti.Slice == 0)) uStart = 2; + if ((ti.Pass == 0) && (ti.Slice == 0)) + { + uStart = 2; + + if (bDataIndependentAddr) + NextAddresses(pbAddrInputZero, pbR, pbTmp); + } ulong uCur = (ti.Lane * ctx.LaneLength) + (ti.Slice * ctx.SegmentLength) + uStart; @@ -506,17 +535,23 @@ namespace KeePassLib.Cryptography.KeyDerivation ulong uPrev = (((uCur % ctx.LaneLength) == 0) ? (uCur + ctx.LaneLength - 1UL) : (uCur - 1UL)); - ulong[] pbR = new ulong[NbBlockSizeInQW]; - ulong[] pbTmp = new ulong[NbBlockSizeInQW]; - - for(ulong i = uStart; i < ctx.SegmentLength; ++i) + for (ulong i = uStart; i < ctx.SegmentLength; ++i) { - if((uCur % ctx.LaneLength) == 1) + if ((uCur % ctx.LaneLength) == 1) uPrev = uCur - 1UL; - ulong uPseudoRand = ctx.Mem[uPrev * NbBlockSizeInQW]; + ulong uPseudoRand; + if (bDataIndependentAddr) + { + ulong iMod = i % NbAddressesInBlock; + if (iMod == 0) + NextAddresses(pbAddrInputZero, pbR, pbTmp); + uPseudoRand = pbAddrInputZero[iMod]; + } + else uPseudoRand = ctx.Mem[uPrev * NbBlockSizeInQW]; + ulong uRefLane = (uPseudoRand >> 32) % ctx.Lanes; - if((ti.Pass == 0) && (ti.Slice == 0)) + if ((ti.Pass == 0) && (ti.Slice == 0)) uRefLane = ti.Lane; ti.Index = i; @@ -536,11 +571,12 @@ namespace KeePassLib.Cryptography.KeyDerivation MemUtil.ZeroArray(pbR); MemUtil.ZeroArray(pbTmp); + if (pbAddrInputZero != null) MemUtil.ZeroArray(pbAddrInputZero); } - catch(Exception) { Debug.Assert(false); } + catch (Exception) { Debug.Assert(false); } try { ti.Finished.Set(); } - catch(Exception) { Debug.Assert(false); } + catch (Exception) { Debug.Assert(false); } } #if ARGON2_B2ROUND_ARRAYS @@ -610,6 +646,19 @@ namespace KeePassLib.Cryptography.KeyDerivation XorBlock(pMem, uNext, pbR, 0); } + private static void NextAddresses(ulong[] pbAddrInputZero, ulong[] pbR, + ulong[] pbTmp) + { + // pbAddrInputZero contains an address block, an input block and a zero block + const ulong uAddr = 0; + const ulong uInput = NbBlockSizeInQW; + const ulong uZero = NbBlockSizeInQW * 2; + + ++pbAddrInputZero[uInput + 6]; + FillBlock(pbAddrInputZero, uZero, uInput, uAddr, false, pbR, pbTmp); + FillBlock(pbAddrInputZero, uZero, uAddr, uAddr, false, pbR, pbTmp); + } + private static byte[] FinalHash(Argon2Ctx ctx, int cbOut, Blake2b h) { ulong[] pqBlockHash = new ulong[NbBlockSizeInQW]; diff --git a/src/KeePassLib2Android/Cryptography/KeyDerivation/Argon2Kdf.cs b/src/KeePassLib2Android/Cryptography/KeyDerivation/Argon2Kdf.cs index 6a7d6e9b..7b0d1183 100644 --- a/src/KeePassLib2Android/Cryptography/KeyDerivation/Argon2Kdf.cs +++ b/src/KeePassLib2Android/Cryptography/KeyDerivation/Argon2Kdf.cs @@ -25,11 +25,22 @@ using System.Text; namespace KeePassLib.Cryptography.KeyDerivation { - public sealed partial class Argon2Kdf : KdfEngine + public enum Argon2Type + { + // The values must be the same as in the Argon2 specification + D = 0, + ID = 2 + } + public sealed partial class Argon2Kdf : KdfEngine { - private static readonly PwUuid g_uuid = new PwUuid(new byte[] { - 0xEF, 0x63, 0x6D, 0xDF, 0x8C, 0x29, 0x44, 0x4B, - 0x91, 0xF7, 0xA9, 0xA4, 0x03, 0xE3, 0x0A, 0x0C }); + + + private static readonly PwUuid g_uuidD = new PwUuid(new byte[] { + 0xEF, 0x63, 0x6D, 0xDF, 0x8C, 0x29, 0x44, 0x4B, + 0x91, 0xF7, 0xA9, 0xA4, 0x03, 0xE3, 0x0A, 0x0C }); + private static readonly PwUuid g_uuidID = new PwUuid(new byte[] { + 0x9E, 0x29, 0x8B, 0x19, 0x56, 0xDB, 0x47, 0x73, + 0xB2, 0x3D, 0xFC, 0x3E, 0xC6, 0xF0, 0xA1, 0xE6 }); public const string ParamSalt = "S"; // Byte[] public const string ParamParallelism = "P"; // UInt32 @@ -55,28 +66,37 @@ namespace KeePassLib.Cryptography.KeyDerivation internal const uint MinParallelism = 1; internal const uint MaxParallelism = (1 << 24) - 1; - internal const ulong DefaultIterations = 2; - internal const ulong DefaultMemory = 1024 * 1024; // 1 MB - internal const uint DefaultParallelism = 2; + internal const ulong DefaultIterations = 2; + internal const ulong DefaultMemory = 64 * 1024 * 1024; // 64 MB + internal const uint DefaultParallelism = 2; - public override PwUuid Uuid - { - get { return g_uuid; } - } + private readonly Argon2Type m_t; - public override string Name - { - get { return "Argon2"; } - } + public override PwUuid Uuid + { + get { return ((m_t == Argon2Type.D) ? g_uuidD : g_uuidID); } + } + public override string Name + { + get { return ((m_t == Argon2Type.D) ? "Argon2d" : "Argon2id"); } + } + + public Argon2Kdf() : this(Argon2Type.D) + { + } + + public Argon2Kdf(Argon2Type t) + { + if ((t != Argon2Type.D) && (t != Argon2Type.ID)) + throw new NotSupportedException(); + + m_t = t; + } public override byte[] GetSeed(KdfParameters p) { return p.GetByteArray(ParamSalt); } - public Argon2Kdf() - { - } - - public override KdfParameters GetDefaultParameters() + public override KdfParameters GetDefaultParameters() { KdfParameters p = base.GetDefaultParameters(); @@ -92,7 +112,7 @@ namespace KeePassLib.Cryptography.KeyDerivation public override void Randomize(KdfParameters p) { if(p == null) { Debug.Assert(false); return; } - Debug.Assert(g_uuid.Equals(p.KdfUuid)); + Debug.Assert(p.KdfUuid.Equals(this.Uuid)); byte[] pb = CryptoRandom.Instance.GetRandomBytes(32); p.SetByteArray(ParamSalt, pb); @@ -128,46 +148,59 @@ namespace KeePassLib.Cryptography.KeyDerivation byte[] pbSecretKey = p.GetByteArray(ParamSecretKey); byte[] pbAssocData = p.GetByteArray(ParamAssocData); - if (pbSecretKey != null) { - throw new ArgumentOutOfRangeException("Unsupported configuration: non-null pbSecretKey"); + byte[] pbRet; + + if (m_t == Argon2Type.ID) + { + pbRet = Argon2Transform(pbMsg, pbSalt, uPar, uMem, + uIt, 32, v, pbSecretKey, pbAssocData); + } + else + { + if (pbSecretKey != null) + { + throw new ArgumentOutOfRangeException("Unsupported configuration: non-null pbSecretKey"); + } + + if (pbAssocData != null) + { + throw new ArgumentOutOfRangeException("Unsupported configuration: non-null pbAssocData"); + } + + /* + byte[] pbRet = Argon2d(pbMsg, pbSalt, uPar, uMem, uIt, + 32, v, pbSecretKey, pbAssocData); + */ + + IntPtr msgPtr = Marshal.AllocHGlobal(pbMsg.Length); + IntPtr saltPtr = Marshal.AllocHGlobal(pbSalt.Length); + IntPtr retPtr = Marshal.AllocHGlobal(32); + Marshal.Copy(pbMsg, 0, msgPtr, pbMsg.Length); + Marshal.Copy(pbSalt, 0, saltPtr, pbSalt.Length); + + const UInt32 Argon2_d = 0; + + int ret = argon2_hash( + (UInt32)uIt, (UInt32)(uMem / 1024), uPar, + msgPtr, (IntPtr)pbMsg.Length, + saltPtr, (IntPtr)pbSalt.Length, + retPtr, (IntPtr)32, + (IntPtr)0, (IntPtr)0, Argon2_d, v); + + if (ret != 0) + { + throw new Exception("argon2_hash failed with " + ret); + } + + pbRet = new byte[32]; + Marshal.Copy(retPtr, pbRet, 0, 32); + + Marshal.FreeHGlobal(msgPtr); + Marshal.FreeHGlobal(saltPtr); + Marshal.FreeHGlobal(retPtr); } - if (pbAssocData != null) { - throw new ArgumentOutOfRangeException("Unsupported configuration: non-null pbAssocData"); - } - - /* - byte[] pbRet = Argon2d(pbMsg, pbSalt, uPar, uMem, uIt, - 32, v, pbSecretKey, pbAssocData); - */ - - IntPtr msgPtr = Marshal.AllocHGlobal(pbMsg.Length); - IntPtr saltPtr = Marshal.AllocHGlobal(pbSalt.Length); - IntPtr retPtr = Marshal.AllocHGlobal(32); - Marshal.Copy(pbMsg, 0, msgPtr, pbMsg.Length); - Marshal.Copy(pbSalt, 0, saltPtr, pbSalt.Length); - - const UInt32 Argon2_d = 0; - - int ret = argon2_hash( - (UInt32)uIt, (UInt32)(uMem / 1024), uPar, - msgPtr, (IntPtr)pbMsg.Length, - saltPtr, (IntPtr)pbSalt.Length, - retPtr, (IntPtr)32, - (IntPtr)0, (IntPtr)0, Argon2_d, v); - - if (ret != 0) { - throw new Exception("argon2_hash failed with " + ret); - } - - byte[] pbRet = new byte[32]; - Marshal.Copy(retPtr, pbRet, 0, 32); - - Marshal.FreeHGlobal(msgPtr); - Marshal.FreeHGlobal(saltPtr); - Marshal.FreeHGlobal(retPtr); - - if(uMem > (100UL * 1024UL * 1024UL)) GC.Collect(); + if(uMem > (100UL * 1024UL * 1024UL)) GC.Collect(); return pbRet; } diff --git a/src/KeePassLib2Android/Cryptography/KeyDerivation/KdfParameters.cs b/src/KeePassLib2Android/Cryptography/KeyDerivation/KdfParameters.cs index 6372d215..600c1f5c 100644 --- a/src/KeePassLib2Android/Cryptography/KeyDerivation/KdfParameters.cs +++ b/src/KeePassLib2Android/Cryptography/KeyDerivation/KdfParameters.cs @@ -1,6 +1,6 @@ /* KeePass Password Safe - The Open-Source Password Manager - Copyright (C) 2003-2017 Dominik Reichl + Copyright (C) 2003-2020 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/src/KeePassLib2Android/Cryptography/KeyDerivation/KdfPool.cs b/src/KeePassLib2Android/Cryptography/KeyDerivation/KdfPool.cs index 8e4f9da9..8f8bfa4a 100644 --- a/src/KeePassLib2Android/Cryptography/KeyDerivation/KdfPool.cs +++ b/src/KeePassLib2Android/Cryptography/KeyDerivation/KdfPool.cs @@ -1,6 +1,6 @@ /* KeePass Password Safe - The Open-Source Password Manager - Copyright (C) 2003-2017 Dominik Reichl + Copyright (C) 2003-2020 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 @@ -41,10 +41,11 @@ namespace KeePassLib.Cryptography.KeyDerivation private static void EnsureInitialized() { - if(g_l.Count > 0) return; + if(g_l.Count != 0) return; g_l.Add(new AesKdf()); - g_l.Add(new Argon2Kdf()); + g_l.Add(new Argon2Kdf(Argon2Type.D)); + g_l.Add(new Argon2Kdf(Argon2Type.ID)); } internal static KdfParameters GetDefaultParameters() diff --git a/src/KeePassLib2Android/KeePassLib2Android.csproj b/src/KeePassLib2Android/KeePassLib2Android.csproj index d6cf5387..fc713789 100644 --- a/src/KeePassLib2Android/KeePassLib2Android.csproj +++ b/src/KeePassLib2Android/KeePassLib2Android.csproj @@ -50,6 +50,7 @@ ..\ProtoBuf\protobuf-net.dll +