/// <summary> /// Parses base parameters from the provided dictionary. /// </summary> /// <param name="dictionary">The dictionary containing KDF parameters.</param> public KdfParameters(VariantDictionary dictionary) { if (dictionary == null) { throw new ArgumentNullException(nameof(dictionary)); } object uuid = dictionary.GetValue(UuidKey); if (uuid == null) { throw new FormatException("No UUID value in dictionary for KdfParameters"); } byte[] uuidBytes = uuid as byte[]; if (uuidBytes == null) { throw new FormatException("UUID value in KdfParameters was not a byte array"); } if (uuidBytes.Length != 16) { throw new FormatException($"Expected 16 UUID bytes in KdfParameters, got {uuidBytes.Length}"); } this.uuid = new Guid(uuidBytes); }
/// <summary> /// Initializes the parameters given a dictionary. /// </summary> /// <param name="dictionary"></param> public Argon2Parameters(VariantDictionary dictionary) : base(dictionary) { this.salt = dictionary.GetValue(SaltKey) as byte[] ?? new byte[0]; this.secretKey = dictionary.GetValue(SecretKey) as byte[] ?? new byte[0]; this.associatedData = dictionary.GetValue(DataKey) as byte[] ?? new byte[0]; uint?dictParallelism = dictionary.GetValue(ParallelismKey) as uint?; if (dictParallelism == null) { throw new FormatException("Could not parse parallelism uint from dictionary"); } this.parallelism = dictParallelism.Value; if (this.parallelism > Argon2d.MaxParallelism || this.parallelism < Argon2d.MinParallelism) { throw new FormatException("Parsed parallelism is out of bounds"); } ulong?dictByteCount = dictionary.GetValue(ByteCountKey) as ulong?; if (dictByteCount == null) { throw new FormatException("Could not parse memory ulong from dictionary"); } this.blockCount = dictByteCount.Value / 1024; if (this.blockCount > (ulong)Argon2d.MaxMemorySize) { throw new FormatException("Parsed block count is higher than allowed"); } ulong?dictIterations = dictionary.GetValue(IterationsKey) as ulong?; if (dictIterations == null) { throw new FormatException("Could not parse iterations ulong from dictionary"); } this.iterations = dictIterations.Value; if (this.iterations < (ulong)Argon2d.MinIterations || this.iterations > (ulong)Argon2d.MaxIterations) { throw new FormatException("Parsed iterations is out of bounds"); } uint?dictVersion = dictionary.GetValue(VersionKey) as uint?; if (dictVersion == null) { throw new FormatException("Argon2 version was not present"); } if (dictVersion.Value != Argon2d.VersionNumber) { throw new FormatException($"Unsupported Argon2 version: {dictVersion.Value}"); } }
/// <summary> /// Initializes the parameters given a dictionary. /// </summary> /// <param name="dictionary"></param> public AesParameters(VariantDictionary dictionary) : base(dictionary) { if (Uuid != AesUuid) { throw new FormatException("Wrong UUID for AesParameters"); } ulong?dictRounds = dictionary.GetValue(RoundsKey) as ulong?; Rounds = dictRounds ?? DefaultRounds; if (!(dictionary.GetValue(SeedKey) is byte[] dictSeed)) { throw new FormatException("AesParameters requires a byte[] seed value"); } Seed = dictSeed.AsBuffer(); }
public static KdfParameters DeserializeExt(byte[] pb) { VariantDictionary d = VariantDictionary.Deserialize(pb); if (d == null) { Debug.Assert(false); return(null); } byte[] pbUuid = d.GetByteArray(ParamUuid); if ((pbUuid == null) || (pbUuid.Length != (int)PwUuid.UuidSize)) { Debug.Assert(false); return(null); } PwUuid pu = new PwUuid(pbUuid); KdfParameters p = new KdfParameters(pu); d.CopyTo(p); return(p); }
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); }
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); }
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 static byte[] SerializeExt(KdfParameters p) { return(VariantDictionary.Serialize(p)); }