static byte [] HashStream(Stream stream, ImageWriter writer, out int strong_name_pointer)
        {
            const int buffer_size = 8192;

            var text                  = writer.GetSection(".text");
            var header_size           = (int)writer.GetHeaderSize();
            var text_section_pointer  = (int)text.PointerToRawData;
            var strong_name_directory = writer.GetStrongNameSignatureDirectory();

            if (strong_name_directory.Size == 0)
            {
                throw new InvalidOperationException();
            }

            strong_name_pointer = (int)(text_section_pointer
                                        + (strong_name_directory.VirtualAddress - text.VirtualAddress));
            var strong_name_length = (int)strong_name_directory.Size;

            var sha1   = new SHA1Managed();
            var buffer = new byte [buffer_size];

            using (var crypto_stream = new CryptoStream(Stream.Null, sha1, CryptoStreamMode.Write)) {
                stream.Seek(0, SeekOrigin.Begin);
                CopyStreamChunk(stream, crypto_stream, buffer, 0xd8);

                crypto_stream.Write(new byte[4], 0, 4);
                stream.Seek(4, SeekOrigin.Current);
                CopyStreamChunk(stream, crypto_stream, buffer, header_size - 0xd8 - 4);

                stream.Seek(text_section_pointer, SeekOrigin.Begin);
                CopyStreamChunk(stream, crypto_stream, buffer, (int)strong_name_pointer - text_section_pointer);

                stream.Seek(strong_name_length, SeekOrigin.Current);
                CopyStreamChunk(stream, crypto_stream, buffer, (int)(text.SizeOfRawData - (strong_name_pointer + strong_name_length - text.PointerToRawData)));

                foreach (Section sect in writer.sections)
                {
                    if (sect.Name == ".text")
                    {
                        continue;
                    }
                    stream.Seek(sect.PointerToRawData, SeekOrigin.Begin);
                    CopyStreamChunk(stream, crypto_stream, buffer, (int)sect.SizeOfRawData);
                }
            }

            return(sha1.Hash);
        }