예제 #1
0
        public void TestGenerateKey32()
        {
            var originalKey = new byte[32];
            var expectedKey = new byte[]
            {
                0xF0, 0xED, 0x57, 0xD5, 0xF0, 0xDA, 0xF3, 0x47,
                0x90, 0xD0, 0xDB, 0x43, 0x25, 0xC6, 0x81, 0x2C,
                0x81, 0x6A, 0x0D, 0x94, 0x96, 0xA9, 0x03, 0xE1,
                0x20, 0xD4, 0x3A, 0x3E, 0x45, 0xAD, 0x02, 0x65
            };
            const ulong rounds = 1;

            var           composite = new CompositeKey();
            AesKdf        kdf       = new AesKdf();
            KdfParameters p         = kdf.GetDefaultParameters();

            p.SetUInt64(AesKdf.ParamRounds, rounds);
            p.SetByteArray(AesKdf.ParamSeed, originalKey);
            var key = composite.GenerateKey32(p);

            Assert.NotNull(key);
            var keyData = key.ReadData();

            Assert.True(MemUtil.ArraysEqual(keyData, expectedKey));
        }
예제 #2
0
        public void TestAesKdf()
        {
            // Up to KeePass 2.34, the OtpKeyProv plugin used the public
            // CompositeKey.TransformKeyManaged method (and a finalizing
            // SHA-256 computation), which became an internal method of
            // the AesKdf class in KeePass 2.35, thus OtpKeyProv now
            // uses the AesKdf class; here we ensure that the results
            // are the same
            var r     = CryptoRandom.NewWeakRandom();
            var pbKey = new byte[32];

            r.NextBytes(pbKey);
            var pbSeed = new byte[32];

            r.NextBytes(pbSeed);
            var uRounds = (ulong)r.Next(1, 0x7FFF);

            var pbMan = new byte[pbKey.Length];

            Array.Copy(pbKey, pbMan, pbKey.Length);
            Assert.True(AesKdf.TransformKeyManaged(pbMan, pbSeed, uRounds));
            pbMan = CryptoUtil.HashSha256(pbMan);

            var kdf = new AesKdf();
            var p   = kdf.GetDefaultParameters();

            p.SetUInt64(AesKdf.ParamRounds, uRounds);
            p.SetByteArray(AesKdf.ParamSeed, pbSeed);
            var pbKdf = kdf.Transform(pbKey, p);

            Assert.True(MemUtil.ArraysEqual(pbMan, pbKdf));
        }
예제 #3
0
        public ProtectedBinary GenerateKey32(byte[] pbKeySeed32, ulong uNumRounds)
        {
            Debug.Assert(pbKeySeed32 != null);
            if (pbKeySeed32 == null)
            {
                throw new ArgumentNullException("pbKeySeed32");
            }
            Debug.Assert(pbKeySeed32.Length == 32);
            if (pbKeySeed32.Length != 32)
            {
                throw new ArgumentException("pbKeySeed32");
            }

            AesKdf        kdf = new AesKdf();
            KdfParameters p   = kdf.GetDefaultParameters();

            p.SetUInt64(AesKdf.ParamRounds, uNumRounds);
            p.SetByteArray(AesKdf.ParamSeed, pbKeySeed32);

            return(GenerateKey32(p));
        }
예제 #4
0
        public override bool Export(PwExportInfo pwExportInfo, Stream sOutput,
                                    IStatusLogger slLogger)
        {
            PwDatabase pd     = pwExportInfo.ContextDatabase;
            PwGroup    pgRoot = pwExportInfo.DataGroup;

            // Remove everything that requires KDBX 4 or higher;
            // see also KdbxFile.GetMinKdbxVersion

            PwUuid puCipher = pd.DataCipherUuid;

            if (puCipher.Equals(ChaCha20Engine.ChaCha20Uuid))
            {
                pd.DataCipherUuid = StandardAesEngine.AesUuid;
            }

            KdfParameters pKdf   = pd.KdfParameters;
            AesKdf        kdfAes = new AesKdf();

            if (!pKdf.KdfUuid.Equals(kdfAes.Uuid))
            {
                pd.KdfParameters = kdfAes.GetDefaultParameters();
            }

            VariantDictionary vdPublic = pd.PublicCustomData;

            pd.PublicCustomData = new VariantDictionary();

            List <PwGroup>            lCustomGK = new List <PwGroup>();
            List <StringDictionaryEx> lCustomGV = new List <StringDictionaryEx>();
            List <PwEntry>            lCustomEK = new List <PwEntry>();
            List <StringDictionaryEx> lCustomEV = new List <StringDictionaryEx>();

            GroupHandler gh = delegate(PwGroup pg)
            {
                if (pg == null)
                {
                    Debug.Assert(false); return(true);
                }
                if (pg.CustomData.Count > 0)
                {
                    lCustomGK.Add(pg);
                    lCustomGV.Add(pg.CustomData);
                    pg.CustomData = new StringDictionaryEx();
                }
                return(true);
            };
            EntryHandler eh = delegate(PwEntry pe)
            {
                if (pe == null)
                {
                    Debug.Assert(false); return(true);
                }
                if (pe.CustomData.Count > 0)
                {
                    lCustomEK.Add(pe);
                    lCustomEV.Add(pe.CustomData);
                    pe.CustomData = new StringDictionaryEx();
                }
                return(true);
            };

            gh(pgRoot);
            pgRoot.TraverseTree(TraversalMethod.PreOrder, gh, eh);

            try
            {
                KdbxFile kdbx = new KdbxFile(pd);
                kdbx.ForceVersion = KdbxFile.FileVersion32_3_1;
                kdbx.Save(sOutput, pgRoot, KdbxFormat.Default, slLogger);
            }
            finally
            {
                // Restore

                pd.DataCipherUuid   = puCipher;
                pd.KdfParameters    = pKdf;
                pd.PublicCustomData = vdPublic;

                for (int i = 0; i < lCustomGK.Count; ++i)
                {
                    lCustomGK[i].CustomData = lCustomGV[i];
                }
                for (int i = 0; i < lCustomEK.Count; ++i)
                {
                    lCustomEK[i].CustomData = lCustomEV[i];
                }
            }

            return(true);
        }
예제 #5
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);
        }