ReadBytes() public method

public ReadBytes ( int nCount ) : byte[]
nCount int
return byte[]
Example #1
0
        private bool ReadInnerHeaderField(BinaryReaderEx br)
        {
            Debug.Assert(br != null);
            if (br == null)
            {
                throw new ArgumentNullException("br");
            }

            byte btFieldID = br.ReadByte();

            int cbSize = MemUtil.BytesToInt32(br.ReadBytes(4));

            if (cbSize < 0)
            {
                throw new FormatException(KLRes.FileCorrupted);
            }

            byte[] pbData = MemUtil.EmptyByteArray;
            if (cbSize > 0)
            {
                pbData = br.ReadBytes(cbSize);
            }

            bool bResult = true;
            KdbxInnerHeaderFieldID kdbID = (KdbxInnerHeaderFieldID)btFieldID;

            switch (kdbID)
            {
            case KdbxInnerHeaderFieldID.EndOfHeader:
                bResult = false;                         // Returning false indicates end of header
                break;

            case KdbxInnerHeaderFieldID.InnerRandomStreamID:
                SetInnerRandomStreamID(pbData);
                break;

            case KdbxInnerHeaderFieldID.InnerRandomStreamKey:
                Debug.Assert(m_pbInnerRandomStreamKey == null);
                m_pbInnerRandomStreamKey = pbData;
                CryptoRandom.Instance.AddEntropy(pbData);
                break;

            case KdbxInnerHeaderFieldID.Binary:
                if (pbData.Length < 1)
                {
                    throw new FormatException();
                }
                KdbxBinaryFlags f     = (KdbxBinaryFlags)pbData[0];
                bool            bProt = ((f & KdbxBinaryFlags.Protected) != KdbxBinaryFlags.None);

                ProtectedBinary pb = new ProtectedBinary(bProt, pbData,
                                                         1, pbData.Length - 1);
                Debug.Assert(m_pbsBinaries.Find(pb) < 0);                         // No deduplication?
                m_pbsBinaries.Add(pb);

                if (bProt)
                {
                    MemUtil.ZeroByteArray(pbData);
                }
                break;

            default:
                Debug.Assert(false);
                break;
            }

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

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

#if KDBX_BENCHMARK
            Stopwatch swTime = Stopwatch.StartNew();
#endif

            m_format   = fmt;
            m_slLogger = slLogger;

            // Other applications might not perform a deduplication
            m_pbsBinaries = new ProtectedBinarySet(false);

            UTF8Encoding encNoBom    = StrUtil.Utf8;
            byte[]       pbCipherKey = null;
            byte[]       pbHmacKey64 = null;

            List <Stream> lStreams = new List <Stream>();
            lStreams.Add(sSource);

            HashingStreamEx sHashing = new HashingStreamEx(sSource, false, null);
            lStreams.Add(sHashing);

            try
            {
                Stream sXml;
                if (fmt == KdbxFormat.Default)
                {
                    BinaryReaderEx br = new BinaryReaderEx(sHashing,
                                                           encNoBom, KLRes.FileCorrupted);
                    byte[] pbHeader = LoadHeader(br);
                    m_pbHashOfHeader = CryptoUtil.HashSha256(pbHeader);

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

                    ComputeKeys(out pbCipherKey, cbEncKey, out pbHmacKey64);

                    string strIncomplete = KLRes.FileHeaderCorrupted + " " +
                                           KLRes.FileIncomplete;

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

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

                        if ((m_pbStreamStartBytes == null) || (m_pbStreamStartBytes.Length != 32))
                        {
                            throw new EndOfStreamException(strIncomplete);
                        }
                        if (!MemUtil.ArraysEqual(pbStoredStartBytes, m_pbStreamStartBytes))
                        {
                            throw new InvalidCompositeKeyException();
                        }

                        sPlain = new HashedBlockStream(sDecrypted, false, 0, !m_bRepairMode);
                    }
                    else                     // KDBX >= 4
                    {
                        byte[] pbStoredHash = MemUtil.Read(sHashing, 32);
                        if ((pbStoredHash == null) || (pbStoredHash.Length != 32))
                        {
                            throw new EndOfStreamException(strIncomplete);
                        }
                        if (!MemUtil.ArraysEqual(m_pbHashOfHeader, pbStoredHash))
                        {
                            throw new InvalidDataException(KLRes.FileHeaderCorrupted);
                        }

                        byte[] pbHeaderHmac = ComputeHeaderHmac(pbHeader, pbHmacKey64);
                        byte[] pbStoredHmac = MemUtil.Read(sHashing, 32);
                        if ((pbStoredHmac == null) || (pbStoredHmac.Length != 32))
                        {
                            throw new EndOfStreamException(strIncomplete);
                        }
                        if (!MemUtil.ArraysEqual(pbHeaderHmac, pbStoredHmac))
                        {
                            throw new InvalidCompositeKeyException();
                        }

                        HmacBlockStream sBlocks = new HmacBlockStream(sHashing,
                                                                      false, !m_bRepairMode, pbHmacKey64);
                        lStreams.Add(sBlocks);

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

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

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

                if (fmt == KdbxFormat.Default)
                {
                    if (m_pbInnerRandomStreamKey == null)
                    {
                        Debug.Assert(false);
                        throw new SecurityException("Invalid inner random stream key!");
                    }

                    m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
                                                            m_pbInnerRandomStreamKey);
                }

#if KeePassDebug_WriteXml
#warning XML output is enabled!

                /* using(FileStream fsOut = new FileStream("Raw.xml", FileMode.Create,
                 *      FileAccess.Write, FileShare.None))
                 * {
                 *      while(true)
                 *      {
                 *              int b = sXml.ReadByte();
                 *              if(b == -1) throw new EndOfStreamException();
                 *              fsOut.WriteByte((byte)b);
                 *      }
                 * } */
#endif

                ReadXmlStreamed(sXml, sHashing);
                // ReadXmlDom(sXml);
            }
            catch (CryptographicException)            // Thrown on invalid padding
            {
                throw new CryptographicException(KLRes.FileCorrupted);
            }
            finally
            {
                if (pbCipherKey != null)
                {
                    MemUtil.ZeroByteArray(pbCipherKey);
                }
                if (pbHmacKey64 != null)
                {
                    MemUtil.ZeroByteArray(pbHmacKey64);
                }

                CommonCleanUpRead(lStreams, sHashing);
            }

#if KDBX_BENCHMARK
            swTime.Stop();
            MessageService.ShowInfo("Loading KDBX took " +
                                    swTime.ElapsedMilliseconds.ToString() + " ms.");
#endif
        }
Example #3
0
        private bool ReadHeaderField(BinaryReaderEx brSource)
        {
            Debug.Assert(brSource != null);
            if (brSource == null)
            {
                throw new ArgumentNullException("brSource");
            }

            byte btFieldID = brSource.ReadByte();

            int cbSize;

            Debug.Assert(m_uFileVersion > 0);
            if (m_uFileVersion < FileVersion32_4)
            {
                cbSize = (int)MemUtil.BytesToUInt16(brSource.ReadBytes(2));
            }
            else
            {
                cbSize = MemUtil.BytesToInt32(brSource.ReadBytes(4));
            }
            if (cbSize < 0)
            {
                throw new FormatException(KLRes.FileCorrupted);
            }

            byte[] pbData = MemUtil.EmptyByteArray;
            if (cbSize > 0)
            {
                pbData = brSource.ReadBytes(cbSize);
            }

            bool bResult            = true;
            KdbxHeaderFieldID kdbID = (KdbxHeaderFieldID)btFieldID;

            switch (kdbID)
            {
            case KdbxHeaderFieldID.EndOfHeader:
                bResult = false;                         // Returning false indicates end of header
                break;

            case KdbxHeaderFieldID.CipherID:
                SetCipher(pbData);
                break;

            case KdbxHeaderFieldID.CompressionFlags:
                SetCompressionFlags(pbData);
                break;

            case KdbxHeaderFieldID.MasterSeed:
                m_pbMasterSeed = pbData;
                CryptoRandom.Instance.AddEntropy(pbData);
                break;

            // Obsolete; for backward compatibility only
            case KdbxHeaderFieldID.TransformSeed:
                Debug.Assert(m_uFileVersion < FileVersion32_4);

                AesKdf kdfS = new AesKdf();
                if (!m_pwDatabase.KdfParameters.KdfUuid.Equals(kdfS.Uuid))
                {
                    m_pwDatabase.KdfParameters = kdfS.GetDefaultParameters();
                }

                // m_pbTransformSeed = pbData;
                m_pwDatabase.KdfParameters.SetByteArray(AesKdf.ParamSeed, pbData);

                CryptoRandom.Instance.AddEntropy(pbData);
                break;

            // Obsolete; for backward compatibility only
            case KdbxHeaderFieldID.TransformRounds:
                Debug.Assert(m_uFileVersion < FileVersion32_4);

                AesKdf kdfR = new AesKdf();
                if (!m_pwDatabase.KdfParameters.KdfUuid.Equals(kdfR.Uuid))
                {
                    m_pwDatabase.KdfParameters = kdfR.GetDefaultParameters();
                }

                // m_pwDatabase.KeyEncryptionRounds = MemUtil.BytesToUInt64(pbData);
                m_pwDatabase.KdfParameters.SetUInt64(AesKdf.ParamRounds,
                                                     MemUtil.BytesToUInt64(pbData));
                break;

            case KdbxHeaderFieldID.EncryptionIV:
                m_pbEncryptionIV = pbData;
                break;

            case KdbxHeaderFieldID.InnerRandomStreamKey:
                Debug.Assert(m_uFileVersion < FileVersion32_4);
                Debug.Assert(m_pbInnerRandomStreamKey == null);
                m_pbInnerRandomStreamKey = pbData;
                CryptoRandom.Instance.AddEntropy(pbData);
                break;

            case KdbxHeaderFieldID.StreamStartBytes:
                Debug.Assert(m_uFileVersion < FileVersion32_4);
                m_pbStreamStartBytes = pbData;
                break;

            case KdbxHeaderFieldID.InnerRandomStreamID:
                Debug.Assert(m_uFileVersion < FileVersion32_4);
                SetInnerRandomStreamID(pbData);
                break;

            case KdbxHeaderFieldID.KdfParameters:
                m_pwDatabase.KdfParameters = KdfParameters.DeserializeExt(pbData);
                break;

            case KdbxHeaderFieldID.PublicCustomData:
                Debug.Assert(m_pwDatabase.PublicCustomData.Count == 0);
                m_pwDatabase.PublicCustomData = VariantDictionary.Deserialize(pbData);
                break;

            default:
                Debug.Assert(false);
                if (m_slLogger != null)
                {
                    m_slLogger.SetText(KLRes.UnknownHeaderId + ": " +
                                       kdbID.ToString() + "!", LogStatusType.Warning);
                }
                break;
            }

            return(bResult);
        }
Example #4
0
        private byte[] LoadHeader(BinaryReaderEx br)
        {
            string strPrevExcpText = br.ReadExceptionText;

            br.ReadExceptionText = KLRes.FileHeaderCorrupted + " " +
                                   KLRes.FileIncompleteExpc;

            MemoryStream msHeader = new MemoryStream();

            Debug.Assert(br.CopyDataTo == null);
            br.CopyDataTo = msHeader;

            byte[] pbSig1 = br.ReadBytes(4);
            uint   uSig1  = MemUtil.BytesToUInt32(pbSig1);

            byte[] pbSig2 = br.ReadBytes(4);
            uint   uSig2  = MemUtil.BytesToUInt32(pbSig2);

            if ((uSig1 == FileSignatureOld1) && (uSig2 == FileSignatureOld2))
            {
                throw new OldFormatException(PwDefs.ShortProductName + @" 1.x",
                                             OldFormatException.OldFormatType.KeePass1x);
            }

            if ((uSig1 == FileSignature1) && (uSig2 == FileSignature2))
            {
            }
            else if ((uSig1 == FileSignaturePreRelease1) && (uSig2 ==
                                                             FileSignaturePreRelease2))
            {
            }
            else
            {
                throw new FormatException(KLRes.FileSigInvalid);
            }

            byte[]     pb           = br.ReadBytes(4);
            uint       uVer         = MemUtil.BytesToUInt32(pb);
            uint       uVerMajor    = uVer & FileVersionCriticalMask;
            uint       uVerMinor    = uVer & ~FileVersionCriticalMask;
            const uint uVerMaxMajor = FileVersion32 & FileVersionCriticalMask;
            const uint uVerMaxMinor = FileVersion32 & ~FileVersionCriticalMask;

            if (uVerMajor > uVerMaxMajor)
            {
                throw new FormatException(KLRes.FileVersionUnsupported +
                                          MessageService.NewParagraph + KLRes.FileNewVerReq);
            }
            if ((uVerMajor == uVerMaxMajor) && (uVerMinor > uVerMaxMinor) &&
                (g_fConfirmOpenUnkVer != null))
            {
                if (!g_fConfirmOpenUnkVer())
                {
                    throw new OperationCanceledException();
                }
            }
            m_uFileVersion = uVer;

            while (true)
            {
                if (!ReadHeaderField(br))
                {
                    break;
                }
            }

            br.CopyDataTo = null;
            byte[] pbHeader = msHeader.ToArray();
            msHeader.Close();

            br.ReadExceptionText = strPrevExcpText;
            return(pbHeader);
        }
Example #5
0
        /// <summary>
        /// Load a KDB file from a stream.
        /// </summary>
        /// <param name="sSource">Stream to read the data from. Must contain
        /// a KDB4 stream.</param>
        /// <param name="kdbFormat">Format specifier.</param>
        /// <param name="slLogger">Status logger (optional).</param>
        public void Load(Stream sSource, Kdb4Format 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 == Kdb4Format.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 == Kdb4Format.PlainXml)
                {
                    readerStream = hashedStream;
                }
                else
                {
                    Debug.Assert(false); throw new FormatException("KdbFormat");
                }

                if (kdbFormat != Kdb4Format.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
                }
                ReadXmlStreamed(readerStream, hashedStream);
                // ReadXmlDom(readerStream);

                readerStream.Close();
                GC.KeepAlive(brDecrypted);
                GC.KeepAlive(br);
            }
            catch (CryptographicException)            // Thrown on invalid padding
            {
                throw new CryptographicException(KLRes.FileCorrupted);
            }
            finally { CommonCleanUpRead(sSource, hashedStream); }
        }
Example #6
0
        private bool ReadHeaderField(BinaryReaderEx brSource)
        {
            Debug.Assert(brSource != null);
            if (brSource == null)
            {
                throw new ArgumentNullException("brSource");
            }

            byte   btFieldID = brSource.ReadByte();
            ushort uSize     = MemUtil.BytesToUInt16(brSource.ReadBytes(2));

            byte[] pbData = null;
            if (uSize > 0)
            {
                string strPrevExcpText = brSource.ReadExceptionText;
                brSource.ReadExceptionText = KLRes.FileHeaderEndEarly;

                pbData = brSource.ReadBytes(uSize);

                brSource.ReadExceptionText = strPrevExcpText;
            }

            bool bResult            = true;
            Kdb4HeaderFieldID kdbID = (Kdb4HeaderFieldID)btFieldID;

            switch (kdbID)
            {
            case Kdb4HeaderFieldID.EndOfHeader:
                bResult = false;                         // Returning false indicates end of header
                break;

            case Kdb4HeaderFieldID.CipherID:
                SetCipher(pbData);
                break;

            case Kdb4HeaderFieldID.CompressionFlags:
                SetCompressionFlags(pbData);
                break;

            case Kdb4HeaderFieldID.MasterSeed:
                m_pbMasterSeed = pbData;
                CryptoRandom.Instance.AddEntropy(pbData);
                break;

            case Kdb4HeaderFieldID.TransformSeed:
                m_pbTransformSeed = pbData;
                CryptoRandom.Instance.AddEntropy(pbData);
                break;

            case Kdb4HeaderFieldID.TransformRounds:
                m_pwDatabase.KeyEncryptionRounds = MemUtil.BytesToUInt64(pbData);
                break;

            case Kdb4HeaderFieldID.EncryptionIV:
                m_pbEncryptionIV = pbData;
                break;

            case Kdb4HeaderFieldID.ProtectedStreamKey:
                m_pbProtectedStreamKey = pbData;
                CryptoRandom.Instance.AddEntropy(pbData);
                break;

            case Kdb4HeaderFieldID.StreamStartBytes:
                m_pbStreamStartBytes = pbData;
                break;

            case Kdb4HeaderFieldID.InnerRandomStreamID:
                SetInnerRandomStreamID(pbData);
                break;

            default:
                Debug.Assert(false);
                if (m_slLogger != null)
                {
                    m_slLogger.SetText(KLRes.UnknownHeaderId + @": " +
                                       kdbID.ToString() + "!", LogStatusType.Warning);
                }
                break;
            }

            return(bResult);
        }
Example #7
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, CancellationToken token)
        {
            Debug.Assert(sSource != null);
            if (sSource == null)
            {
                throw new ArgumentNullException("sSource");
            }

            this.m_format   = kdbFormat;
            this.m_slLogger = slLogger;

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

            var encNoBom = StrUtil.Utf8;

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

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

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

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

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

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

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

                    if (this.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 (this.m_pbProtectedStreamKey == null)
                    {
                        Debug.Assert(false);
                        throw new SecurityException("Invalid protected stream key!");
                    }

                    this.m_randomStream = new CryptoRandomStream(
                        this.m_craInnerRandomStream,
                        this.m_pbProtectedStreamKey);
                }
                else
                {
                    this.m_randomStream = null; // No random stream for plain-text files
                }

                this.ReadXmlStreamed(readerStream, hashedStream, token);

                readerStream.Dispose();
            }
            finally
            {
                this.CommonCleanUpRead(sSource, hashedStream);
            }
        }