private void OnKdfChange(object sender, Preference.PreferenceChangeEventArgs preferenceChangeEventArgs)
        {
            var db = App.Kp2a.GetDb();
            var previousKdfParams = db.KpDatabase.KdfParameters;

            Kp2aLog.Log("previous kdf: " + KdfPool.Get(db.KpDatabase.KdfParameters.KdfUuid) + " " + db.KpDatabase.KdfParameters.KdfUuid.ToHexString());
            db.KpDatabase.KdfParameters =
                KdfPool.Get(
                    new PwUuid(MemUtil.HexStringToByteArray((string)preferenceChangeEventArgs.NewValue)))
                .GetDefaultParameters();

            Kp2aLog.Log("--new    kdf: " + KdfPool.Get(db.KpDatabase.KdfParameters.KdfUuid) + " " + db.KpDatabase.KdfParameters.KdfUuid.ToHexString());

            SaveDb save = new SaveDb(Activity, App.Kp2a, new ActionOnFinish((success, message) =>
            {
                if (!success)
                {
                    db.KpDatabase.KdfParameters = previousKdfParams;
                    Toast.MakeText(Activity, message, ToastLength.Long).Show();
                    return;
                }
                UpdateKdfScreen();
            }));
            ProgressTask pt = new ProgressTask(App.Kp2a, Activity, save);

            pt.Run();
        }
Ejemplo n.º 2
0
        public async Task Create(Credentials credentials, string name, DatabaseVersion version = DatabaseVersion.V4)
        {
            try
            {
                await Task.Run(() =>
                {
                    var compositeKey = CreateCompositeKey(credentials);
                    var ioConnection = IOConnectionInfo.FromByteArray(new byte[] {});

                    _pwDatabase.New(ioConnection, compositeKey);
                    _pwDatabase.Name           = name;
                    _pwDatabase.RootGroup.Name = name;

                    _credentials = credentials;

                    switch (version)
                    {
                    case DatabaseVersion.V4:
                        _pwDatabase.KdfParameters  = KdfPool.Get("Argon2").GetDefaultParameters();
                        _pwDatabase.DataCipherUuid = CipherPool.GlobalPool[1].CipherUuid;
                        break;
                    }
                });
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message, ex);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Generate a 32-byte (256-bit) key from the composite key.
        /// </summary>
        public ProtectedBinary GenerateKey32(KdfParameters p)
        {
            if (p == null)
            {
                Debug.Assert(false); throw new ArgumentNullException("p");
            }

            byte[]          pbRaw32 = null, pbTrf32 = null;
            ProtectedBinary pbRet   = null;

            try
            {
                pbRaw32 = CreateRawCompositeKey32();
                if ((pbRaw32 == null) || (pbRaw32.Length != 32))
                {
                    Debug.Assert(false); return(null);
                }

                KdfEngine kdf = KdfPool.Get(p.KdfUuid);
                if (kdf == null)                // CryptographicExceptions are translated to "file corrupted"
                {
                    throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
                                        KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
                                        "UUID: " + p.KdfUuid.ToHexString() + ".");
                }

                pbTrf32 = kdf.Transform(pbRaw32, p);
                if (pbTrf32 == null)
                {
                    Debug.Assert(false); return(null);
                }
                if (pbTrf32.Length != 32)
                {
                    Debug.Assert(false);
                    pbTrf32 = CryptoUtil.HashSha256(pbTrf32);
                }

                pbRet = new ProtectedBinary(true, pbTrf32);
            }
            finally
            {
                if (pbRaw32 != null)
                {
                    MemUtil.ZeroByteArray(pbRaw32);
                }
                if (pbTrf32 != null)
                {
                    MemUtil.ZeroByteArray(pbTrf32);
                }
            }

            return(pbRet);
        }
Ejemplo n.º 4
0
        private void KdfTestTh(object o)
        {
            string strMsg = KLRes.UnknownError;

            try
            {
                KdfParameters p = (o as KdfParameters);
                if (p == null)
                {
                    Debug.Assert(false); return;
                }

                KdfEngine kdf = KdfPool.Get(p.KdfUuid);
                if (kdf == null)
                {
                    Debug.Assert(false); return;
                }

                byte[] pbMsg = new byte[32];
                Program.GlobalRandom.NextBytes(pbMsg);

                kdf.Randomize(p);

                Stopwatch sw = Stopwatch.StartNew();
                kdf.Transform(pbMsg, p);
                sw.Stop();

                long lMS = sw.ElapsedMilliseconds;
                lMS = Math.Max(lMS, 1L);
                double dS = (double)lMS / 1000.0;

                strMsg = KPRes.TestSuccess + MessageService.NewParagraph +
                         KPRes.TransformTime.Replace(@"{PARAM}", dS.ToString());
            }
            catch (ThreadAbortException)
            {
                try { Thread.ResetAbort(); }
                catch (Exception) { Debug.Assert(false); }
                return;
            }
            catch (Exception ex)
            {
                Debug.Assert(false);
                if ((ex != null) && !string.IsNullOrEmpty(ex.Message))
                {
                    strMsg = ex.Message;
                }
            }
            finally { m_thKdf = null; }             // Before continuation, to enable controls

            try { m_btnOK.Invoke(new KdfsDelegate(this.KdfTestPost), strMsg); }
            catch (Exception) { Debug.Assert(false); }
        }
Ejemplo n.º 5
0
        private void SetKdfParameters(KdfParameters p)
        {
            if (p == null)
            {
                Debug.Assert(false); return;
            }

            KdfEngine kdf = KdfPool.Get(p.KdfUuid);

            if (kdf == null)
            {
                Debug.Assert(false); return;
            }

            for (int i = 0; i < m_cmbKdf.Items.Count; ++i)
            {
                string strKdf = (m_cmbKdf.Items[i] as string);
                if (string.IsNullOrEmpty(strKdf))
                {
                    Debug.Assert(false); continue;
                }

                if (strKdf.Equals(kdf.Name, StrUtil.CaseIgnoreCmp))
                {
                    bool bPrevInit = m_bInitializing;
                    m_bInitializing = true;                     // Prevent selection handler

                    m_cmbKdf.SelectedIndex = i;

                    m_bInitializing = bPrevInit;
                    break;
                }
            }

            if (kdf is AesKdf)
            {
                ulong uIt = p.GetUInt64(AesKdf.ParamRounds,
                                        PwDefs.DefaultKeyEncryptionRounds);
                SetKdfParameters(uIt, 1024, 2);
            }
            else if (kdf is Argon2Kdf)
            {
                ulong uIt = p.GetUInt64(Argon2Kdf.ParamIterations,
                                        Argon2Kdf.DefaultIterations);
                ulong uMem = p.GetUInt64(Argon2Kdf.ParamMemory,
                                         Argon2Kdf.DefaultMemory);
                uint uPar = p.GetUInt32(Argon2Kdf.ParamParallelism,
                                        Argon2Kdf.DefaultParallelism);
                SetKdfParameters(uIt, uMem, uPar);
            }
            // else { Debug.Assert(false); } // Plugins may provide other KDFs
        }
        private void UpdateKdfScreen()
        {
            var db  = App.Kp2a.GetDb();
            var kdf = KdfPool.Get(db.KpDatabase.KdfParameters.KdfUuid);

            var kdfpref = FindPreference(GetString(Resource.String.kdf_key));


            kdfpref.Summary = kdf.Name;

            var kdfscreen = ((PreferenceScreen)FindPreference(GetString(Resource.String.kdf_screen_key)));

            if (kdf is AesKdf)
            {
                if (kdfscreen.FindPreference(GetString(Resource.String.rounds_key)) == null)
                {
                    kdfscreen.AddPreference(aesRounds);
                }
                kdfscreen.RemovePreference(argon2rounds);
                kdfscreen.RemovePreference(argon2memory);
                kdfscreen.RemovePreference(argon2parallelism);

                aesRounds.Enabled = db.CanWrite;
                UpdateKdfSummary(aesRounds);
            }
            else
            {
                kdfscreen.RemovePreference(aesRounds);
                if (kdfscreen.FindPreference("argon2rounds") == null)
                {
                    kdfscreen.AddPreference(argon2rounds);
                    kdfscreen.AddPreference(argon2memory);
                    kdfscreen.AddPreference(argon2parallelism);
                }
                UpdateKdfSummary(argon2rounds);
                UpdateKdfSummary(argon2memory);
                UpdateKdfSummary(argon2parallelism);
            }
        }
Ejemplo n.º 7
0
        // public void Save(string strFile, PwGroup pgDataSource, KdbxFormat fmt,
        //	IStatusLogger slLogger)
        // {
        //	bool bMadeUnhidden = UrlUtil.UnhideFile(strFile);
        //
        //	IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFile);
        //	this.Save(IOConnection.OpenWrite(ioc), pgDataSource, format, slLogger);
        //
        //	if(bMadeUnhidden) UrlUtil.HideFile(strFile, true); // Hide again
        // }

        /// <summary>
        /// Save the contents of the current <c>PwDatabase</c> to a KDBX file.
        /// </summary>
        /// <param name="sSaveTo">Stream to write the KDBX file into.</param>
        /// <param name="pgDataSource">Group containing all groups and
        /// entries to write. If <c>null</c>, the complete database will
        /// be written.</param>
        /// <param name="fmt">Format of the file to create.</param>
        /// <param name="slLogger">Logger that recieves status information.</param>
        public void Save(Stream sSaveTo, PwGroup pgDataSource, KdbxFormat fmt,
                         IStatusLogger slLogger)
        {
            Debug.Assert(sSaveTo != null);
            if (sSaveTo == null)
            {
                throw new ArgumentNullException("sSaveTo");
            }

            if (m_bUsedOnce)
            {
                throw new InvalidOperationException("Do not reuse KdbxFile objects!");
            }
            m_bUsedOnce = true;

            m_format    = fmt;
            m_slLogger  = slLogger;
            m_xmlWriter = null;

            PwGroup      pgRoot   = (pgDataSource ?? m_pwDatabase.RootGroup);
            UTF8Encoding encNoBom = StrUtil.Utf8;
            CryptoRandom cr       = CryptoRandom.Instance;

            byte[] pbCipherKey = null;
            byte[] pbHmacKey64 = null;

            m_pbsBinaries.Clear();
            m_pbsBinaries.AddFrom(pgRoot);

            List <Stream> lStreams = new List <Stream>();

            lStreams.Add(sSaveTo);

            HashingStreamEx sHashing = new HashingStreamEx(sSaveTo, true, null);

            lStreams.Add(sHashing);

            try
            {
                m_uFileVersion = GetMinKdbxVersion();

                int           cbEncKey, cbEncIV;
                ICipherEngine iCipher = GetCipher(out cbEncKey, out cbEncIV);

                m_pbMasterSeed   = cr.GetRandomBytes(32);
                m_pbEncryptionIV = cr.GetRandomBytes((uint)cbEncIV);

                // m_pbTransformSeed = cr.GetRandomBytes(32);
                PwUuid    puKdf = m_pwDatabase.KdfParameters.KdfUuid;
                KdfEngine kdf   = KdfPool.Get(puKdf);
                if (kdf == null)
                {
                    throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
                                        // KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
                                        "UUID: " + puKdf.ToHexString() + ".");
                }
                kdf.Randomize(m_pwDatabase.KdfParameters);

                if (m_format == KdbxFormat.Default)
                {
                    if (m_uFileVersion < FileVersion32_4)
                    {
                        m_craInnerRandomStream   = CrsAlgorithm.Salsa20;
                        m_pbInnerRandomStreamKey = cr.GetRandomBytes(32);
                    }
                    else                     // KDBX >= 4
                    {
                        m_craInnerRandomStream   = CrsAlgorithm.ChaCha20;
                        m_pbInnerRandomStreamKey = cr.GetRandomBytes(64);
                    }

                    m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
                                                            m_pbInnerRandomStreamKey);
                }

                if (m_uFileVersion < FileVersion32_4)
                {
                    m_pbStreamStartBytes = cr.GetRandomBytes(32);
                }

                Stream sXml;
                if (m_format == KdbxFormat.Default)
                {
                    byte[] pbHeader = GenerateHeader();
                    m_pbHashOfHeader = CryptoUtil.HashSha256(pbHeader);

                    MemUtil.Write(sHashing, pbHeader);
                    sHashing.Flush();

                    ComputeKeys(out pbCipherKey, cbEncKey, out pbHmacKey64);

                    Stream sPlain;
                    if (m_uFileVersion < FileVersion32_4)
                    {
                        Stream sEncrypted = EncryptStream(sHashing, iCipher,
                                                          pbCipherKey, cbEncIV, true);
                        if ((sEncrypted == null) || (sEncrypted == sHashing))
                        {
                            throw new SecurityException(KLRes.CryptoStreamFailed);
                        }
                        lStreams.Add(sEncrypted);

                        MemUtil.Write(sEncrypted, m_pbStreamStartBytes);

                        sPlain = new HashedBlockStream(sEncrypted, true);
                    }
                    else                     // KDBX >= 4
                    {
                        // For integrity checking (without knowing the master key)
                        MemUtil.Write(sHashing, m_pbHashOfHeader);

                        byte[] pbHeaderHmac = ComputeHeaderHmac(pbHeader, pbHmacKey64);
                        MemUtil.Write(sHashing, pbHeaderHmac);

                        Stream sBlocks = new HmacBlockStream(sHashing, true,
                                                             true, pbHmacKey64);
                        lStreams.Add(sBlocks);

                        sPlain = EncryptStream(sBlocks, iCipher, pbCipherKey,
                                               cbEncIV, true);
                        if ((sPlain == null) || (sPlain == sBlocks))
                        {
                            throw new SecurityException(KLRes.CryptoStreamFailed);
                        }
                    }
                    lStreams.Add(sPlain);

                    if (m_pwDatabase.Compression == PwCompressionAlgorithm.GZip)
                    {
                        sXml = new GZipStream(sPlain, CompressionMode.Compress);
                        lStreams.Add(sXml);
                    }
                    else
                    {
                        sXml = sPlain;
                    }

                    if (m_uFileVersion >= FileVersion32_4)
                    {
                        WriteInnerHeader(sXml);                         // Binary header before XML
                    }
                }
                else if (m_format == KdbxFormat.PlainXml)
                {
                    sXml = sHashing;
                }
                else
                {
                    Debug.Assert(false);
                    throw new ArgumentOutOfRangeException("fmt");
                }

                m_xmlWriter = XmlUtilEx.CreateXmlWriter(sXml);

                WriteDocument(pgRoot);

                m_xmlWriter.Flush();
            }
            finally
            {
                CommonCleanUpWrite(lStreams, sHashing);

                if (pbCipherKey != null)
                {
                    MemUtil.ZeroByteArray(pbCipherKey);
                }
                if (pbHmacKey64 != null)
                {
                    MemUtil.ZeroByteArray(pbHmacKey64);
                }
            }
        }
Ejemplo n.º 8
0
 private KdfEngine GetKdf()
 {
     return(KdfPool.Get(m_cmbKdf.Text));
 }
Ejemplo n.º 9
0
        // public void Save(string strFile, PwGroup pgDataSource, KdbxFormat fmt,
        //	IStatusLogger slLogger)
        // {
        //	bool bMadeUnhidden = UrlUtil.UnhideFile(strFile);
        //
        //	IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFile);
        //	this.Save(IOConnection.OpenWrite(ioc), pgDataSource, format, slLogger);
        //
        //	if(bMadeUnhidden) UrlUtil.HideFile(strFile, true); // Hide again
        // }

        /// <summary>
        /// Save the contents of the current <c>PwDatabase</c> to a KDBX file.
        /// </summary>
        /// <param name="sSaveTo">Stream to write the KDBX file into.</param>
        /// <param name="pgDataSource">Group containing all groups and
        /// entries to write. If <c>null</c>, the complete database will
        /// be written.</param>
        /// <param name="fmt">Format of the file to create.</param>
        /// <param name="slLogger">Logger that recieves status information.</param>
        public void Save(Stream sSaveTo, PwGroup pgDataSource, KdbxFormat fmt,
                         IStatusLogger slLogger)
        {
            Debug.Assert(sSaveTo != null);
            if (sSaveTo == null)
            {
                throw new ArgumentNullException("sSaveTo");
            }

            if (m_bUsedOnce)
            {
                throw new InvalidOperationException("Do not reuse KdbxFile objects!");
            }
            m_bUsedOnce = true;

            m_format    = fmt;
            m_slLogger  = slLogger;
            m_xmlWriter = null;

            PwGroup      pgRoot   = (pgDataSource ?? m_pwDatabase.RootGroup);
            UTF8Encoding encNoBom = StrUtil.Utf8;
            CryptoRandom cr       = CryptoRandom.Instance;

            byte[] pbCipherKey = null;
            byte[] pbHmacKey64 = null;

            m_pbsBinaries = new ProtectedBinarySet(true);
            m_pbsBinaries.AddFrom(pgRoot);

            List <Stream> lStreams = new List <Stream>();

            lStreams.Add(sSaveTo);

            HashingStreamEx sHashing = new HashingStreamEx(sSaveTo, true, null);

            lStreams.Add(sHashing);

            try
            {
                // Fix history entries (should not be necessary; just for safety,
                // as e.g. XPath searches depend on correct history entry UUIDs)
                if (m_pwDatabase.MaintainBackups())
                {
                    Debug.Assert(false);
                }

                m_uFileVersion = GetMinKdbxVersion();

                int           cbEncKey, cbEncIV;
                ICipherEngine iCipher = GetCipher(out cbEncKey, out cbEncIV);

                m_pbMasterSeed   = cr.GetRandomBytes(32);
                m_pbEncryptionIV = cr.GetRandomBytes((uint)cbEncIV);

                // m_pbTransformSeed = cr.GetRandomBytes(32);
                PwUuid    puKdf = m_pwDatabase.KdfParameters.KdfUuid;
                KdfEngine kdf   = KdfPool.Get(puKdf);
                if (kdf == null)
                {
                    throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
                                        // KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
                                        "UUID: " + puKdf.ToHexString() + ".");
                }
                kdf.Randomize(m_pwDatabase.KdfParameters);

                if (m_format == KdbxFormat.Default)
                {
                    if (m_uFileVersion < FileVersion32_4)
                    {
                        m_craInnerRandomStream   = CrsAlgorithm.Salsa20;
                        m_pbInnerRandomStreamKey = cr.GetRandomBytes(32);
                    }
                    else                     // KDBX >= 4
                    {
                        m_craInnerRandomStream   = CrsAlgorithm.ChaCha20;
                        m_pbInnerRandomStreamKey = cr.GetRandomBytes(64);
                    }

                    m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
                                                            m_pbInnerRandomStreamKey);
                }

                if (m_uFileVersion < FileVersion32_4)
                {
                    m_pbStreamStartBytes = cr.GetRandomBytes(32);
                }

                Stream sXml;
                if (m_format == KdbxFormat.Default || m_format == KdbxFormat.ProtocolBuffers)
                {
                    byte[] pbHeader = GenerateHeader();
                    m_pbHashOfHeader = CryptoUtil.HashSha256(pbHeader);

                    MemUtil.Write(sHashing, pbHeader);
                    sHashing.Flush();

                    ComputeKeys(out pbCipherKey, cbEncKey, out pbHmacKey64);

                    Stream sPlain;
                    if (m_uFileVersion < FileVersion32_4)
                    {
                        Stream sEncrypted = EncryptStream(sHashing, iCipher,
                                                          pbCipherKey, cbEncIV, true);
                        if ((sEncrypted == null) || (sEncrypted == sHashing))
                        {
                            throw new SecurityException(KLRes.CryptoStreamFailed);
                        }
                        lStreams.Add(sEncrypted);

                        MemUtil.Write(sEncrypted, m_pbStreamStartBytes);

                        sPlain = new HashedBlockStream(sEncrypted, true);
                    }
                    else                     // KDBX >= 4
                    {
                        // For integrity checking (without knowing the master key)
                        MemUtil.Write(sHashing, m_pbHashOfHeader);

                        byte[] pbHeaderHmac = ComputeHeaderHmac(pbHeader, pbHmacKey64);
                        MemUtil.Write(sHashing, pbHeaderHmac);

                        Stream sBlocks = new HmacBlockStream(sHashing, true,
                                                             true, pbHmacKey64);
                        lStreams.Add(sBlocks);

                        sPlain = EncryptStream(sBlocks, iCipher, pbCipherKey,
                                               cbEncIV, true);
                        if ((sPlain == null) || (sPlain == sBlocks))
                        {
                            throw new SecurityException(KLRes.CryptoStreamFailed);
                        }
                    }
                    lStreams.Add(sPlain);

                    if (m_pwDatabase.Compression == PwCompressionAlgorithm.GZip)
                    {
                        sXml = new GZipStream(sPlain, CompressionMode.Compress);
                        lStreams.Add(sXml);
                    }
                    else
                    {
                        sXml = sPlain;
                    }

                    if (m_uFileVersion >= FileVersion32_4)
                    {
                        WriteInnerHeader(sXml);                         // Binary header before XML
                    }
                }
                else if (m_format == KdbxFormat.PlainXml)
                {
                    sXml = sHashing;
                }
                else
                {
                    Debug.Assert(false);
                    throw new ArgumentOutOfRangeException("fmt");
                }

                var stopWatch = Stopwatch.StartNew();

                if (m_format == KdbxFormat.ProtocolBuffers)
                {
                    KdbpFile.WriteDocument(m_pwDatabase, sXml, m_pbInnerRandomStreamKey, m_pbHashOfHeader);
                }
                else
                {
#if KeePassUAP
                    XmlWriterSettings xws = new XmlWriterSettings();
                    xws.Encoding            = encNoBom;
                    xws.Indent              = true;
                    xws.IndentChars         = "\t";
                    xws.NewLineOnAttributes = false;

                    XmlWriter xw = XmlWriter.Create(sXml, xws);
#else
                    XmlTextWriter xw = new XmlTextWriter(sXml, encNoBom);

                    xw.Formatting  = Formatting.Indented;
                    xw.IndentChar  = '\t';
                    xw.Indentation = 1;
#endif
                    m_xmlWriter = xw;

                    WriteDocument(pgRoot);

                    m_xmlWriter.Flush();
                    m_xmlWriter.Close();
                }
                Kp2aLog.Log(String.Format("{1}: {0}ms", stopWatch.ElapsedMilliseconds, m_format == KdbxFormat.ProtocolBuffers ? "KdbpFile.WriteDocument" : "Xml WriteDocument"));
            }
            finally
            {
                if (pbCipherKey != null)
                {
                    MemUtil.ZeroByteArray(pbCipherKey);
                }
                if (pbHmacKey64 != null)
                {
                    MemUtil.ZeroByteArray(pbHmacKey64);
                }

                CommonCleanUpWrite(lStreams, sHashing);
            }
        }