Exemple #1
0
        /// <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);
            }
        }
Exemple #2
0
        /// <summary>
        /// Saves current document to stream.
        /// </summary>
        /// <param name="stream">Stream.</param>
        public void Save(Stream stream)
        {
            using (var timer = new Medo.Diagnostics.LifetimeWatch("Save")) {
                stream.Write(this.PasswordSalt, 0, this.PasswordSalt.Length);

                var buffer = new List <byte>(65536);
                buffer.AddRange(new byte[] { 0x41, 0x31, 0x32, 0x38 });
                foreach (var item in this.Items)
                {
                    var bytes = item.GetBytes();
                    buffer.AddRange(GetInt32Bytes(bytes.Length));
                    buffer.AddRange(bytes);
                }
                buffer.AddRange(new byte[] { 0x41, 0x31, 0x32, 0x38 });

                byte[] encBuffer;
                using (var enc = this.Crypto.CreateEncryptor()) {
                    encBuffer = enc.TransformFinalBlock(buffer.ToArray(), 0, buffer.Count);
                }

                stream.Write(encBuffer, 0, encBuffer.Length);
            }
        }