示例#1
0
        /// <summary>
        /// Load a KDB file from a stream.
        /// </summary>
        /// <param name="sSource">Stream to read the data from. Must contain
        /// a KDBX stream.</param>
        /// <param name="kdbFormat">Format specifier.</param>
        /// <param name="slLogger">Status logger (optional).</param>
        public void Load(Stream sSource, KdbxFormat kdbFormat, IStatusLogger slLogger)
        {
            Debug.Assert(sSource != null);
            if (sSource == null)
            {
                throw new ArgumentNullException("sSource");
            }

            m_format   = kdbFormat;
            m_slLogger = slLogger;

            HashingStreamEx hashedStream = new HashingStreamEx(sSource, false, null);

            UTF8Encoding encNoBom = StrUtil.Utf8;

            try
            {
                BinaryReaderEx br           = null;
                BinaryReaderEx brDecrypted  = null;
                Stream         readerStream = null;

                if (kdbFormat == KdbxFormat.Default)
                {
                    br = new BinaryReaderEx(hashedStream, encNoBom, KLRes.FileCorrupted);
                    ReadHeader(br);

                    Stream sDecrypted = AttachStreamDecryptor(hashedStream);
                    if ((sDecrypted == null) || (sDecrypted == hashedStream))
                    {
                        throw new SecurityException(KLRes.CryptoStreamFailed);
                    }

                    brDecrypted = new BinaryReaderEx(sDecrypted, encNoBom, KLRes.FileCorrupted);
                    byte[] pbStoredStartBytes = brDecrypted.ReadBytes(32);

                    if ((m_pbStreamStartBytes == null) || (m_pbStreamStartBytes.Length != 32))
                    {
                        throw new InvalidDataException();
                    }

                    for (int iStart = 0; iStart < 32; ++iStart)
                    {
                        if (pbStoredStartBytes[iStart] != m_pbStreamStartBytes[iStart])
                        {
                            throw new InvalidCompositeKeyException();
                        }
                    }

                    Stream sHashed = new HashedBlockStream(sDecrypted, false, 0,
                                                           !m_bRepairMode);

                    if (m_pwDatabase.Compression == PwCompressionAlgorithm.GZip)
                    {
                        readerStream = new GZipStream(sHashed, CompressionMode.Decompress);
                    }
                    else
                    {
                        readerStream = sHashed;
                    }
                }
                else if (kdbFormat == KdbxFormat.PlainXml)
                {
                    readerStream = hashedStream;
                }
                else
                {
                    Debug.Assert(false); throw new FormatException("KdbFormat");
                }

                if (kdbFormat != KdbxFormat.PlainXml)                // Is an encrypted format
                {
                    if (m_pbProtectedStreamKey == null)
                    {
                        Debug.Assert(false);
                        throw new SecurityException("Invalid protected stream key!");
                    }

                    m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
                                                            m_pbProtectedStreamKey);
                }
                else
                {
                    m_randomStream = null;                  // No random stream for plain-text files
                }
#if KeePassDebug_WriteXml
                // FileStream fsOut = new FileStream("Raw.xml", FileMode.Create,
                //	FileAccess.Write, FileShare.None);
                // try
                // {
                //	while(true)
                //	{
                //		int b = readerStream.ReadByte();
                //		if(b == -1) break;
                //		fsOut.WriteByte((byte)b);
                //	}
                // }
                // catch(Exception) { }
                // fsOut.Close();
#endif

                ReadXmlStreamed(readerStream, hashedStream);
                // ReadXmlDom(readerStream);

                readerStream.Dispose();
                // GC.KeepAlive(br);
                // GC.KeepAlive(brDecrypted);
            }
#if !KeePass2PCL
            catch (CryptographicException)            // Thrown on invalid padding
            {
                throw new CryptographicException(KLRes.FileCorrupted);
            }
#endif
            finally { CommonCleanUpRead(sSource, hashedStream); }
        }
示例#2
0
        // public void Save(string strFile, PwGroup pgDataSource, KdbxFormat format,
        //	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="format">Format of the file to create.</param>
        /// <param name="slLogger">Logger that recieves status information.</param>
        public void Save(Stream sSaveTo, PwGroup pgDataSource, KdbxFormat format,
                         IStatusLogger slLogger)
        {
            Debug.Assert(sSaveTo != null);
            if (sSaveTo == null)
            {
                throw new ArgumentNullException("sSaveTo");
            }

            m_format   = format;
            m_slLogger = slLogger;

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

            UTF8Encoding encNoBom = StrUtil.Utf8;
            CryptoRandom cr       = CryptoRandom.Instance;

            try
            {
                m_pbMasterSeed    = cr.GetRandomBytes(32);
                m_pbTransformSeed = cr.GetRandomBytes(32);
                m_pbEncryptionIV  = cr.GetRandomBytes(16);

                m_pbProtectedStreamKey = cr.GetRandomBytes(32);
                m_craInnerRandomStream = CrsAlgorithm.Salsa20;
                m_randomStream         = new CryptoRandomStream(m_craInnerRandomStream,
                                                                m_pbProtectedStreamKey);

                m_pbStreamStartBytes = cr.GetRandomBytes(32);

                Stream writerStream;
                if (m_format == KdbxFormat.Default)
                {
                    WriteHeader(hashedStream);                     // Also flushes the stream

                    Stream sEncrypted = AttachStreamEncryptor(hashedStream);
                    if ((sEncrypted == null) || (sEncrypted == hashedStream))
                    {
                        throw new SecurityException(KLRes.CryptoStreamFailed);
                    }

                    sEncrypted.Write(m_pbStreamStartBytes, 0, m_pbStreamStartBytes.Length);

                    Stream sHashed = new HashedBlockStream(sEncrypted, true);

                    if (m_pwDatabase.Compression == PwCompressionAlgorithm.GZip)
                    {
                        writerStream = new GZipStream(sHashed, CompressionMode.Compress);
                    }
                    else
                    {
                        writerStream = sHashed;
                    }
                }
                else if (m_format == KdbxFormat.PlainXml)
                {
                    writerStream = hashedStream;
                }
                else
                {
                    Debug.Assert(false); throw new FormatException("KdbFormat");
                }

#if KeePass2PCL
                var settings = new XmlWriterSettings()
                {
                    Encoding     = encNoBom,
                    Indent       = true,
                    IndentChars  = "\t",
                    NewLineChars = "\r\n",
                };
                m_xmlWriter = XmlWriter.Create(writerStream, settings);
#else
                m_xmlWriter = new XmlTextWriter(writerStream, encNoBom);
#endif
                WriteDocument(pgDataSource);

                m_xmlWriter.Flush();
                m_xmlWriter.Dispose();
                writerStream.Dispose();
            }
            finally { CommonCleanUpWrite(sSaveTo, hashedStream); }
        }