public override byte[] Transform(byte[] pbMsg, KdfParameters p) { if(pbMsg == null) throw new ArgumentNullException("pbMsg"); if(p == null) throw new ArgumentNullException("p"); Type tRounds = p.GetTypeOf(ParamRounds); if(tRounds == null) throw new ArgumentNullException("p.Rounds"); if(tRounds != typeof(ulong)) throw new ArgumentOutOfRangeException("p.Rounds"); ulong uRounds = p.GetUInt64(ParamRounds, 0); byte[] pbSeed = p.GetByteArray(ParamSeed); if(pbSeed == null) throw new ArgumentNullException("p.Seed"); if(pbMsg.Length != 32) { Debug.Assert(false); pbMsg = CryptoUtil.HashSha256(pbMsg); } if(pbSeed.Length != 32) { Debug.Assert(false); pbSeed = CryptoUtil.HashSha256(pbSeed); } return TransformKey(pbMsg, pbSeed, uRounds); }
public override void Randomize(KdfParameters p) { if(p == null) { Debug.Assert(false); return; } Debug.Assert(g_uuid.Equals(p.KdfUuid)); byte[] pbSeed = CryptoRandom.Instance.GetRandomBytes(32); p.SetByteArray(ParamSeed, pbSeed); }
private byte[] GenerateHeader() { byte[] pbHeader; using (MemoryStream ms = new MemoryStream()) { MemUtil.Write(ms, MemUtil.UInt32ToBytes(FileSignature1)); MemUtil.Write(ms, MemUtil.UInt32ToBytes(FileSignature2)); MemUtil.Write(ms, MemUtil.UInt32ToBytes(m_uFileVersion)); WriteHeaderField(ms, KdbxHeaderFieldID.CipherID, m_pwDatabase.DataCipherUuid.UuidBytes); int nCprID = (int)m_pwDatabase.Compression; WriteHeaderField(ms, KdbxHeaderFieldID.CompressionFlags, MemUtil.UInt32ToBytes((uint)nCprID)); WriteHeaderField(ms, KdbxHeaderFieldID.MasterSeed, m_pbMasterSeed); if (m_uFileVersion < FileVersion32_4) { Debug.Assert(m_pwDatabase.KdfParameters.KdfUuid.Equals( (new AesKdf()).Uuid)); WriteHeaderField(ms, KdbxHeaderFieldID.TransformSeed, m_pwDatabase.KdfParameters.GetByteArray(AesKdf.ParamSeed)); WriteHeaderField(ms, KdbxHeaderFieldID.TransformRounds, MemUtil.UInt64ToBytes(m_pwDatabase.KdfParameters.GetUInt64( AesKdf.ParamRounds, PwDefs.DefaultKeyEncryptionRounds))); } else { WriteHeaderField(ms, KdbxHeaderFieldID.KdfParameters, KdfParameters.SerializeExt(m_pwDatabase.KdfParameters)); } if (m_pbEncryptionIV.Length > 0) { WriteHeaderField(ms, KdbxHeaderFieldID.EncryptionIV, m_pbEncryptionIV); } if (m_uFileVersion < FileVersion32_4) { WriteHeaderField(ms, KdbxHeaderFieldID.InnerRandomStreamKey, m_pbInnerRandomStreamKey); WriteHeaderField(ms, KdbxHeaderFieldID.StreamStartBytes, m_pbStreamStartBytes); int nIrsID = (int)m_craInnerRandomStream; WriteHeaderField(ms, KdbxHeaderFieldID.InnerRandomStreamID, MemUtil.Int32ToBytes(nIrsID)); } // Write public custom data only when there is at least one item, // because KDBX 3.1 didn't support this field yet if (m_pwDatabase.PublicCustomData.Count > 0) { WriteHeaderField(ms, KdbxHeaderFieldID.PublicCustomData, VariantDictionary.Serialize(m_pwDatabase.PublicCustomData)); } WriteHeaderField(ms, KdbxHeaderFieldID.EndOfHeader, new byte[] { (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }); pbHeader = ms.ToArray(); } return(pbHeader); }
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); }
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 KdfParameters pKdf = pd.KdfParameters; AesKdf kdfAes = new AesKdf(); if (!kdfAes.Uuid.Equals(pKdf.KdfUuid)) { 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; kdbx.Save(sOutput, pgRoot, KdbxFormat.Default, slLogger); } finally { // Restore 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); }
private KdfParameters GetKdfParameters(bool bShowAdjustments) { KdfEngine kdf = GetKdf(); if (kdf == null) { Debug.Assert(false); return(null); } string strAdj = string.Empty; KdfParameters pKdf = kdf.GetDefaultParameters(); if (kdf is AesKdf) { pKdf.SetUInt64(AesKdf.ParamRounds, (ulong)m_numKdfIt.Value); } else if (kdf is Argon2Kdf) { ulong uIt = (ulong)m_numKdfIt.Value; AdjustKdfParam <ulong>(ref uIt, ">=", Argon2Kdf.MinIterations, KPRes.Iterations, ref strAdj); AdjustKdfParam <ulong>(ref uIt, "<=", Argon2Kdf.MaxIterations, KPRes.Iterations, ref strAdj); pKdf.SetUInt64(Argon2Kdf.ParamIterations, uIt); // Adjust parallelism first, as memory depends on it uint uPar = (uint)m_numKdfPar.Value; AdjustKdfParam <uint>(ref uPar, ">=", Argon2Kdf.MinParallelism, KPRes.Parallelism, ref strAdj); uint uParMax = Argon2Kdf.MaxParallelism; int cp = Environment.ProcessorCount; if ((cp > 0) && (cp <= (int.MaxValue / 2))) { uParMax = Math.Min(uParMax, (uint)(cp * 2)); } AdjustKdfParam <uint>(ref uPar, "<=", uParMax, KPRes.Parallelism, ref strAdj); pKdf.SetUInt32(Argon2Kdf.ParamParallelism, uPar); ulong uMem = (ulong)m_numKdfMem.Value; int iMemUnit = m_cmbKdfMem.SelectedIndex; while (iMemUnit > 0) { if (uMem > (ulong.MaxValue / 1024UL)) { uMem = ulong.MaxValue; break; } uMem *= 1024UL; --iMemUnit; } // 8*p blocks = 1024*8*p bytes minimum memory, see spec Debug.Assert(Argon2Kdf.MinMemory == (1024UL * 8UL)); ulong uMemMin = Argon2Kdf.MinMemory * uPar; AdjustKdfParam <ulong>(ref uMem, ">=", uMemMin, KPRes.Memory, ref strAdj); AdjustKdfParam <ulong>(ref uMem, "<=", Argon2Kdf.MaxMemory, KPRes.Memory, ref strAdj); pKdf.SetUInt64(Argon2Kdf.ParamMemory, uMem); } else { return(null); // Plugins may handle it } if (bShowAdjustments && (strAdj.Length > 0)) { strAdj = KPRes.KdfAdjust + MessageService.NewParagraph + strAdj; MessageService.ShowInfo(strAdj); } return(pKdf); }
private void OnBtnOK(object sender, EventArgs e) { m_pwDatabase.SettingsChanged = DateTime.UtcNow; if (m_tbDbName.Text != m_pwDatabase.Name) { m_pwDatabase.Name = m_tbDbName.Text; m_pwDatabase.NameChanged = DateTime.UtcNow; } string strNew = m_tbDbDesc.Text; string strOrgFlt = StrUtil.NormalizeNewLines(m_pwDatabase.Description, false); string strNewFlt = StrUtil.NormalizeNewLines(strNew, false); if (strNewFlt != strOrgFlt) { m_pwDatabase.Description = strNew; m_pwDatabase.DescriptionChanged = DateTime.UtcNow; } if (m_tbDefaultUser.Text != m_pwDatabase.DefaultUserName) { m_pwDatabase.DefaultUserName = m_tbDefaultUser.Text; m_pwDatabase.DefaultUserNameChanged = DateTime.UtcNow; } if (!m_cbColor.Checked) { m_pwDatabase.Color = Color.Empty; } else { m_pwDatabase.Color = m_clr; } int nCipher = CipherPool.GlobalPool.GetCipherIndex(m_cmbEncAlgo.Text); Debug.Assert(nCipher >= 0); if (nCipher >= 0) { m_pwDatabase.DataCipherUuid = CipherPool.GlobalPool[nCipher].CipherUuid; } else { m_pwDatabase.DataCipherUuid = StandardAesEngine.AesUuid; } // m_pwDatabase.KeyEncryptionRounds = (ulong)m_numKdfIt.Value; KdfParameters pKdf = GetKdfParameters(true); if (pKdf != null) { m_pwDatabase.KdfParameters = pKdf; } // No assert, plugins may assign KDF parameters if (m_rbNone.Checked) { m_pwDatabase.Compression = PwCompressionAlgorithm.None; } else if (m_rbGZip.Checked) { m_pwDatabase.Compression = PwCompressionAlgorithm.GZip; } else { Debug.Assert(false); } // m_pwDatabase.MemoryProtection.ProtectTitle = UpdateMemoryProtection(0, // m_pwDatabase.MemoryProtection.ProtectTitle, PwDefs.TitleField); // m_pwDatabase.MemoryProtection.ProtectUserName = UpdateMemoryProtection(1, // m_pwDatabase.MemoryProtection.ProtectUserName, PwDefs.UserNameField); // m_pwDatabase.MemoryProtection.ProtectPassword = UpdateMemoryProtection(2, // m_pwDatabase.MemoryProtection.ProtectPassword, PwDefs.PasswordField); // m_pwDatabase.MemoryProtection.ProtectUrl = UpdateMemoryProtection(3, // m_pwDatabase.MemoryProtection.ProtectUrl, PwDefs.UrlField); // m_pwDatabase.MemoryProtection.ProtectNotes = UpdateMemoryProtection(4, // m_pwDatabase.MemoryProtection.ProtectNotes, PwDefs.NotesField); // m_pwDatabase.MemoryProtection.AutoEnableVisualHiding = m_cbAutoEnableHiding.Checked; if (m_cbRecycleBin.Checked != m_pwDatabase.RecycleBinEnabled) { m_pwDatabase.RecycleBinEnabled = m_cbRecycleBin.Checked; m_pwDatabase.RecycleBinChanged = DateTime.UtcNow; } int iRecBinSel = m_cmbRecycleBin.SelectedIndex; if (m_dictRecycleBinGroups.ContainsKey(iRecBinSel)) { if (!m_dictRecycleBinGroups[iRecBinSel].Equals(m_pwDatabase.RecycleBinUuid)) { m_pwDatabase.RecycleBinUuid = m_dictRecycleBinGroups[iRecBinSel]; m_pwDatabase.RecycleBinChanged = DateTime.UtcNow; } } else { Debug.Assert(false); if (!PwUuid.Zero.Equals(m_pwDatabase.RecycleBinUuid)) { m_pwDatabase.RecycleBinUuid = PwUuid.Zero; m_pwDatabase.RecycleBinChanged = DateTime.UtcNow; } } int iTemplSel = m_cmbEntryTemplates.SelectedIndex; if (m_dictEntryTemplateGroups.ContainsKey(iTemplSel)) { if (!m_dictEntryTemplateGroups[iTemplSel].Equals(m_pwDatabase.EntryTemplatesGroup)) { m_pwDatabase.EntryTemplatesGroup = m_dictEntryTemplateGroups[iTemplSel]; m_pwDatabase.EntryTemplatesGroupChanged = DateTime.UtcNow; } } else { Debug.Assert(false); if (!PwUuid.Zero.Equals(m_pwDatabase.EntryTemplatesGroup)) { m_pwDatabase.EntryTemplatesGroup = PwUuid.Zero; m_pwDatabase.EntryTemplatesGroupChanged = DateTime.UtcNow; } } if (!m_cbHistoryMaxItems.Checked) { m_pwDatabase.HistoryMaxItems = -1; } else { m_pwDatabase.HistoryMaxItems = (int)m_numHistoryMaxItems.Value; } if (!m_cbHistoryMaxSize.Checked) { m_pwDatabase.HistoryMaxSize = -1; } else { m_pwDatabase.HistoryMaxSize = (long)m_numHistoryMaxSize.Value * 1024 * 1024; } m_pwDatabase.MaintainBackups(); // Apply new history settings if (!m_cbKeyRec.Checked) { m_pwDatabase.MasterKeyChangeRec = -1; } else { m_pwDatabase.MasterKeyChangeRec = (long)m_numKeyRecDays.Value; } if (!m_cbKeyForce.Checked) { m_pwDatabase.MasterKeyChangeForce = -1; } else { m_pwDatabase.MasterKeyChangeForce = (long)m_numKeyForceDays.Value; } m_pwDatabase.MasterKeyChangeForceOnce = m_cbKeyForceOnce.Checked; }
public override byte[] ProcessBlock( byte[] @in, int inOff, int inLen) { if (ForEncryption) { if (KeyPairGenerator != null) { EphemeralKeyPair ephKeyPair = KeyPairGenerator.Generate(); PrivParam = ephKeyPair.GetKeyPair().Private; V = ephKeyPair.GetEncodedPublicKey(); } } else { if (KeyParser != null) { MemoryStream bIn = new MemoryStream(@in, inOff, inLen) { Position = SecureHeadSize }; try { PubParam = KeyParser.ReadKey(bIn); } catch (IOException e) { throw new InvalidCipherTextException("unable to recover ephemeral public key: " + e.Message, e); } catch (ArgumentException e) { throw new InvalidCipherTextException("unable to recover ephemeral public key: " + e.Message, e); } int encLength = (inLen - (int)(bIn.Length - bIn.Position)); V = Arrays.CopyOfRange(@in, inOff + SecureHeadSize, inOff + encLength); } } // Compute the common value and convert to byte array. Agree.Init(PrivParam); BigInteger z = Agree.CalculateAgreement(PubParam); byte[] bigZ = BigIntegers.AsUnsignedByteArray(Agree.GetFieldSize(), z); try { // Initialise the KDF. KdfParameters kdfParam = new KdfParameters(bigZ, null); Kdf.Init(kdfParam); byte[] temp = new byte[inLen - SecureHeadSize]; Array.Copy(@in, inOff + SecureHeadSize, temp, 0, temp.Length); return(ForEncryption ? EncryptBlock(@in, inOff, inLen) : DecryptBlock(temp, inOff, temp.Length)); } finally { Arrays.Fill(bigZ, 0); } }
private byte[] DecryptBlock( byte[] in_enc, int inOff, int inLen, byte[] z) { byte[] M = null; KeyParameter macKey = null; KdfParameters kParam = new KdfParameters(z, param.GetDerivationV()); int macKeySize = param.MacKeySize; kdf.Init(kParam); // Ensure that the length of the input is greater than the MAC in bytes if (inLen < mac.GetMacSize()) { throw new InvalidCipherTextException("Length of input must be greater than the MAC"); } inLen -= mac.GetMacSize(); if (cipher == null) // stream mode { byte[] Buffer = GenerateKdfBytes(kParam, inLen + (macKeySize / 8)); M = new byte[inLen]; for (int i = 0; i != inLen; i++) { M[i] = (byte)(in_enc[inOff + i] ^ Buffer[i]); } macKey = new KeyParameter(Buffer, inLen, (macKeySize / 8)); } else { int cipherKeySize = ((IesWithCipherParameters)param).CipherKeySize; byte[] Buffer = GenerateKdfBytes(kParam, (cipherKeySize / 8) + (macKeySize / 8)); cipher.Init(false, new KeyParameter(Buffer, 0, (cipherKeySize / 8))); M = cipher.DoFinal(in_enc, inOff, inLen); macKey = new KeyParameter(Buffer, (cipherKeySize / 8), (macKeySize / 8)); } byte[] macIV = param.GetEncodingV(); mac.Init(macKey); mac.BlockUpdate(in_enc, inOff, inLen); mac.BlockUpdate(macIV, 0, macIV.Length); mac.DoFinal(macBuf, 0); inOff += inLen; byte[] T1 = Arrays.CopyOfRange(in_enc, inOff, inOff + macBuf.Length); if (!Arrays.ConstantTimeAreEqual(T1, macBuf)) { throw (new InvalidCipherTextException("Invalid MAC.")); } return(M); }