internal static BimilItem Parse(BimilDocument document, byte[] buffer, int offset, int count) { if (count < 4) { throw new FormatException("Invalid buffer size."); } var res = new BimilItem(document); var currOffset = offset; while (currOffset < (offset + count)) { var keyLength = GetInt32(buffer, currOffset); var valueLength = GetInt32(buffer, currOffset + 4); var type = (BimilRecordFormat)GetInt32(buffer, currOffset + 8); var key = BimilValue.Parse(document, buffer, currOffset + 12, keyLength); var value = BimilValue.Parse(document, buffer, currOffset + 12 + keyLength, valueLength); res.Records.Add(new BimilRecord(document, key.Text, value.Text, type)); currOffset += 12 + keyLength + valueLength; } if (currOffset != (offset + count)) { throw new FormatException("Invalid buffer content."); } return(res); }
/// <summary> /// Returns document. /// </summary> /// <param name="stream">Stream.</param> /// <param name="password">Password.</param> /// <exception cref="FormatException">Cannot parse document.</exception> public static BimilDocument Open(Stream stream, string password) { try { using (var timer = new Medo.Diagnostics.LifetimeWatch("Open")) { var doc = new BimilDocument(); var salt = new byte[16]; stream.Read(salt, 0, 16); doc.PasswordSalt = salt; var deriveBytes = new Rfc2898DeriveBytes(UTF8Encoding.UTF8.GetBytes(password), doc.PasswordSalt, 4096); doc.Crypto.Key = deriveBytes.GetBytes(16); doc.Crypto.IV = deriveBytes.GetBytes(16); var encBuffer = new byte[stream.Length - 16]; stream.Read(encBuffer, 0, encBuffer.Length); byte[] decBuffer; using (var dec = doc.Crypto.CreateDecryptor()) { decBuffer = dec.TransformFinalBlock(encBuffer, 0, encBuffer.Length); } if ((decBuffer[0] == 0x41) && (decBuffer[1] == 0x31) && (decBuffer[2] == 0x32) && (decBuffer[3] == 0x38)) { if ((decBuffer[decBuffer.Length - 4] != 0x41) || (decBuffer[decBuffer.Length - 3] != 0x31) || (decBuffer[decBuffer.Length - 2] != 0x32) || (decBuffer[decBuffer.Length - 1] != 0x38)) { throw new FormatException("Invalid secondary identifier."); } doc.Id = "A128"; } else { throw new FormatException("Invalid primary identifier."); } var currOffset = 4; while (currOffset < (decBuffer.Length - 4)) { var itemLen = GetInt32(decBuffer, currOffset); var item = BimilItem.Parse(doc, decBuffer, currOffset + 4, itemLen); doc.Items.Add(item); currOffset += 4 + itemLen; } return(doc); } } catch (CryptographicException ex) { throw new FormatException("Cannot parse document.", ex); } catch (OverflowException ex) { throw new FormatException("Cannot parse document.", ex); } catch (SecurityException ex) { throw new FormatException("Cannot parse document.", ex); } }
internal static BimilValue Parse(BimilDocument document, byte[] buffer, int offset, int count) { var encBuffer = new byte[count]; Buffer.BlockCopy(buffer, offset, encBuffer, 0, count); return(new BimilValue(document) { Bytes = encBuffer }); }
/// <summary> /// Saves current document to stream using another password. Current document is not affected. /// </summary> /// <param name="stream">Stream.</param> /// <param name="newPassword">Password.</param> public void Save(Stream stream, string newPassword) { using (var newDoc = new BimilDocument(newPassword)) { foreach (var item in this.Items) { var newItem = newDoc.AddItem(item.Name, item.IconIndex); foreach (var record in item.Records) { newItem.AddRecord(record.Key.Text, record.Value.Text, record.Format); } } newDoc.Save(stream); } }
internal BimilValue(BimilDocument document) { this.Document = document; this.Text = ""; }
internal BimilItem(BimilDocument document) { this.Document = document; this.Records = new List <BimilRecord>(); }