Пример #1
0
        /**
         * Decrypt the Document-/SummaryInformation and other optionally streams.
         * Opposed to other crypto modes, cryptoapi is record based and can't be used
         * to stream-decrypt a whole file
         *
         * @see <a href="http://msdn.microsoft.com/en-us/library/dd943321(v=office.12).aspx">2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream</a>
         */

        public override InputStream GetDataStream(DirectoryNode dir)
        {
            NPOIFSFileSystem    fsOut = new NPOIFSFileSystem();
            DocumentNode        es    = (DocumentNode)dir.GetEntry("EncryptedSummary");
            DocumentInputStream dis   = dir.CreateDocumentInputStream(es);
            MemoryStream        bos   = new MemoryStream();

            IOUtils.Copy(dis, bos);
            dis.Close();
            SeekableMemoryStream    sbis    = new SeekableMemoryStream(bos.ToArray());
            LittleEndianInputStream leis    = new LittleEndianInputStream(sbis);
            int streamDescriptorArrayOffset = (int)leis.ReadUInt();
            int streamDescriptorArraySize   = (int)leis.ReadUInt();

            sbis.Seek(streamDescriptorArrayOffset - 8, SeekOrigin.Current);// sbis.Skip(streamDescriptorArrayOffset - 8);

            sbis.SetBlock(0);
            int encryptedStreamDescriptorCount = (int)leis.ReadUInt();

            StreamDescriptorEntry[] entries = new StreamDescriptorEntry[encryptedStreamDescriptorCount];
            for (int i = 0; i < encryptedStreamDescriptorCount; i++)
            {
                StreamDescriptorEntry entry = new StreamDescriptorEntry();
                entries[i]         = entry;
                entry.streamOffset = (int)leis.ReadUInt();
                entry.streamSize   = (int)leis.ReadUInt();
                entry.block        = leis.ReadUShort();
                int nameSize = leis.ReadUByte();
                entry.flags = leis.ReadUByte();
                bool IsStream = StreamDescriptorEntry.flagStream.IsSet(entry.flags);
                entry.reserved2  = leis.ReadInt();
                entry.streamName = StringUtil.ReadUnicodeLE(leis, nameSize);
                leis.ReadShort();
                Debug.Assert(entry.streamName.Length == nameSize);
            }

            foreach (StreamDescriptorEntry entry in entries)
            {
                sbis.Seek(entry.streamOffset);
                sbis.SetBlock(entry.block);
                Stream is1 = new BufferedStream(sbis, entry.streamSize);
                fsOut.CreateDocument(is1, entry.streamName);
            }

            leis.Close();
            sbis = null;

            bos.Seek(0, SeekOrigin.Begin); //bos.Reset();
            fsOut.WriteFileSystem(bos);
            fsOut.Close();
            _length = bos.Length;
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.ToArray());

            throw new NotImplementedException("ByteArrayInputStream should be derived from InputStream");
        }
Пример #2
0
        /**
         * Encrypt the Document-/SummaryInformation and other optionally streams.
         * Opposed to other crypto modes, cryptoapi is record based and can't be used
         * to stream-encrypt a whole file
         *
         * @see <a href="http://msdn.microsoft.com/en-us/library/dd943321(v=office.12).aspx">2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream</a>
         */
        public override OutputStream GetDataStream(DirectoryNode dir)
        {
            CipherByteArrayOutputStream bos = new CipherByteArrayOutputStream(this);

            byte[] buf = new byte[8];

            bos.Write(buf, 0, 8); // skip header
            String[] entryNames =
            {
                SummaryInformation.DEFAULT_STREAM_NAME,
                DocumentSummaryInformation.DEFAULT_STREAM_NAME
            };

            List <StreamDescriptorEntry> descList = new List <StreamDescriptorEntry>();

            int block = 0;

            foreach (String entryName in entryNames)
            {
                if (!dir.HasEntry(entryName))
                {
                    continue;
                }
                StreamDescriptorEntry descEntry = new StreamDescriptorEntry();
                descEntry.block        = block;
                descEntry.streamOffset = (int)bos.Length;
                descEntry.streamName   = entryName;
                descEntry.flags        = StreamDescriptorEntry.flagStream.SetValue(0, 1);
                descEntry.reserved2    = 0;

                bos.SetBlock(block);
                DocumentInputStream dis = dir.CreateDocumentInputStream(entryName);
                IOUtils.Copy(dis, bos);
                dis.Close();

                descEntry.streamSize = (int)(bos.Length - descEntry.streamOffset);
                descList.Add(descEntry);

                dir.GetEntry(entryName).Delete();

                block++;
            }

            int streamDescriptorArrayOffset = (int)bos.Length;

            bos.SetBlock(0);
            LittleEndian.PutUInt(buf, 0, descList.Count);
            bos.Write(buf, 0, 4);

            foreach (StreamDescriptorEntry sde in descList)
            {
                LittleEndian.PutUInt(buf, 0, sde.streamOffset);
                bos.Write(buf, 0, 4);
                LittleEndian.PutUInt(buf, 0, sde.streamSize);
                bos.Write(buf, 0, 4);
                LittleEndian.PutUShort(buf, 0, sde.block);
                bos.Write(buf, 0, 2);
                LittleEndian.PutUByte(buf, 0, (short)sde.streamName.Length);
                bos.Write(buf, 0, 1);
                LittleEndian.PutUByte(buf, 0, (short)sde.flags);
                bos.Write(buf, 0, 1);
                LittleEndian.PutUInt(buf, 0, sde.reserved2);
                bos.Write(buf, 0, 4);
                byte[] nameBytes = StringUtil.GetToUnicodeLE(sde.streamName);
                bos.Write(nameBytes, 0, nameBytes.Length);
                LittleEndian.PutShort(buf, 0, (short)0); // null-termination
                bos.Write(buf, 0, 2);
            }

            int savedSize = (int)bos.Length;
            int streamDescriptorArraySize = savedSize - streamDescriptorArrayOffset;

            LittleEndian.PutUInt(buf, 0, streamDescriptorArrayOffset);
            LittleEndian.PutUInt(buf, 4, streamDescriptorArraySize);

            bos.Reset();
            bos.SetBlock(0);
            bos.Write(buf, 0, 8);
            bos.SetSize(savedSize);

            dir.CreateDocument("EncryptedSummary", new MemoryStream(bos.GetBuf(), 0, savedSize));
            DocumentSummaryInformation dsi = PropertySetFactory.NewDocumentSummaryInformation();

            try
            {
                dsi.Write(dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME);
            }
            catch (WritingNotSupportedException e)
            {
                throw new IOException(e.Message);
            }

            //return bos;
            throw new NotImplementedException("CipherByteArrayOutputStream should be derived from OutputStream");
        }