Пример #1
0
            private void ValidateTable(BitSplitter bs)
            {
                int pointer = (int)bs.GetInteger(8);

                if (pointer != 0)
                {
                    throw new DemuxException("Non-zero pointers are not currently supported");
                }

                int table_id = (int)bs.GetInteger(8);

                if (table_id != 0x02)
                {
                    throw new DemuxException("Wrong table ID for PMT");
                }

                SectionSyntax = bs.GetFlag();
                if (!SectionSyntax)
                {
                    throw new DemuxException("Invalid PMT: incorrect section syntax");
                }
                bool zero = bs.GetFlag();

                if (zero)
                {
                    throw new DemuxException("Invalid PMT: zero bit wasn't zero");
                }
            }
Пример #2
0
            /// <summary>
            /// Digest a PES payload into structured table.
            /// Does not handle split-payloads -- agregate payloads before calling
            /// </summary>
            public PES(byte[] RawPayload)
            {
                BitSplitter bs = new BitSplitter(RawPayload);

                int start_code = (int)bs.GetInteger(24);

                if (start_code != 1)
                {
                    throw new DemuxException("Invalid PES: start code prefix missing");
                }

                PTS = DTS = -1;

                StreamId     = (int)bs.GetInteger(8);
                PacketLength = (int)bs.GetInteger(16);

                // Both these methods set 'FrameData'
                if (SpecialStream(StreamId))
                {
                    ReadSpecialForm(bs);
                }
                else
                {
                    DecodeElementaryStream(bs);
                }
            }
Пример #3
0
            private void ReadSpecialForm(BitSplitter bs)
            {
                byte[] data = bs.RemainingBytes();
                if (data.Length < PacketLength)
                {
                    throw new DemuxException("Invalid PES: packet shorter than described");
                }
                MemoryStream ms = new MemoryStream(data, 0, PacketLength);

                FrameData = ms.ToArray();
            }
Пример #4
0
 private void ReadTransportHeader(BitSplitter bs)
 {
     bs.SkipToNextByte();                 // Sync byte
     Error            = bs.GetFlag();
     StartIndicator   = bs.GetFlag();
     HighPriority     = bs.GetFlag();
     PID              = (int)bs.GetInteger(13);
     ScrambleCode     = (int)bs.GetInteger(2);
     HasAdaptionField = bs.GetFlag();
     HasPayload       = bs.GetFlag();
     Counter          = (int)bs.GetInteger(4);
 }
Пример #5
0
 private void CheckPayloadType(BitSplitter bs)
 {
     if (payload.Length > 4)
     {
         if (payload[0] == 0 && payload[1] == 0 && payload[2] == 0x01)
         {
             PayloadIs_PES = true;
         }
     }
     if (!PayloadIs_PES && HasPayload && StartIndicator)
     {
         if (payload[0] != 0x00)
         {
             throw new DemuxException("Non-zero pointer values are not yet supported!");
         }
         TableId = payload[1];
     }
 }
Пример #6
0
            private void CheckAdaptionField(BitSplitter bs)
            {
                if (HasAdaptionField)
                {
                    int adaption_end = (int)bs.GetInteger(8);
                    adaption_end += bs.ByteOffset;
                    Discont       = bs.GetFlag();
                    KeyFrame      = bs.GetFlag();
                    ES_Prio       = bs.GetFlag();
                    HasPCR        = bs.GetFlag();
                    HasOPCR       = bs.GetFlag();
                    HasSplice     = bs.GetFlag();
                    PrivateFlag   = bs.GetFlag();
                    AdapExtFlag   = bs.GetFlag();
                    if (bs.BitOffset != 0)
                    {
                        throw new Exception("bit align problem");
                    }

                    if (HasPCR)
                    {
                        PCR = (long)bs.GetInteger(33);
                        bs.SkipBits(15);                         // throw away useless sync stuff.
                    }
                    if (HasOPCR)
                    {
                        bs.SkipBits(48);                              // throw away useless "old" timecode
                    }
                    if (HasSplice)
                    {
                        bs.SkipBits(8);                                // throw away splice counter
                    }
                    if (PrivateFlag)
                    {
                        int priv_len = (int)bs.GetInteger(8);
                        bs.SkipBytes(priv_len);                         // skip private data
                    }
                    // ignore the rest of the adaption field (it's mostly to support stuff we ignore)
                    int skip_len = adaption_end - bs.ByteOffset;
                    bs.SkipBytes(skip_len);
                }
            }
Пример #7
0
            /// <summary>
            /// Decode the bizzare PTS format
            /// </summary>
            private void ReadPTS(BitSplitter bs)
            {
                int marker = (int)bs.GetInteger(4);

                if (marker != 2)
                {
                    throw new DemuxException("Invalid PES: PTS marker incorrect");
                }
                long part_1 = (long)bs.GetInteger(3);

                bs.SkipBits(1);
                long part_2 = (long)bs.GetInteger(15);

                bs.SkipBits(1);
                long part_3 = (long)bs.GetInteger(15);

                bs.SkipBits(1);
                unchecked {                 // allow overflow so we can catch it later:
                    PTS = (UInt32)(part_3 + (part_2 << 15) + (part_1 << 30));
                }
            }
Пример #8
0
            /// <summary>
            /// Reads the long list of flags in the default PES header.
            /// </summary>
            private void ReadFlags(BitSplitter bs)
            {
                ScrambleControl = (int)bs.GetInteger(2);
                HighPriority    = bs.GetFlag();
                HasAlignment    = bs.GetFlag();
                IsCopyright     = bs.GetFlag();
                IsOriginal      = bs.GetFlag();
                HasPTS          = bs.GetFlag();
                HasDTS          = bs.GetFlag();

                if (HasDTS && !HasPTS)
                {
                    throw new DemuxException("Invalid PES: DTS without PTS is not allowed");
                }

                HasESCR         = bs.GetFlag();
                HasEsRate       = bs.GetFlag();
                UsesTrickMode   = bs.GetFlag();
                MoreCopyright   = bs.GetFlag();
                HasPesCRC       = bs.GetFlag();
                HasPesExtension = bs.GetFlag();
            }
Пример #9
0
            /// <summary>Digest data into structured packet</summary>
            public Packet(byte[] RawPacket)
            {
                if (RawPacket[0] != 0x47)
                {
                    throw new DemuxException("Sync byte missing");
                }

                PCR = -1; TableId = -1; PayloadIs_PES = false;

                BitSplitter bs = new BitSplitter(RawPacket);

                ReadTransportHeader(bs);

                if (PID == 0x1FFF)
                {
                    return;                                // null packet
                }
                CheckAdaptionField(bs);

                payload = bs.RemainingBytes();

                CheckPayloadType(bs);
            }
Пример #10
0
            private int SectionNumber, LastSection;             // should always be zero

            /// <summary>
            /// Digest a packet payload into structured table. Payload should be from the pointer field onward.
            /// Does not yet handle multi-packet tables
            /// </summary>
            public PAT(byte[] RawPayload)
            {
                Map = new Dictionary <int, int>();
                BitSplitter bs = new BitSplitter(RawPayload);

                ValidateTable(bs);

                bs.SkipBits(2);                 // reserved;
                SectionLength = (int)bs.GetInteger(12);
                TransportID   = (int)bs.GetInteger(16);
                bs.SkipBits(2);                 // reserved
                Version       = (int)bs.GetInteger(5);
                IsCurrent     = bs.GetFlag();
                SectionNumber = (int)bs.GetInteger(8);
                LastSection   = (int)bs.GetInteger(8);

                int bits_left = (SectionLength - 5) - 4;                 // remaining length in bytes, excluding CRC
                int items     = bits_left / 4;

                for (int i = 0; i < items; i++)
                {
                    int prog = (int)bs.GetInteger(16);
                    bs.SkipBits(3);
                    int pid = (int)bs.GetInteger(13);
                    if (!Map.ContainsKey(prog))
                    {
                        Map.Add(prog, pid);
                    }
                    else
                    {
                        throw new DemuxException("Invalid PAT: program number specified more than once (" + prog + ")");
                    }
                }

                // Ignoring CRC.
            }
Пример #11
0
 private void ReadExtendedHeader(BitSplitter bs)
 {
     // not yet implemented
 }
Пример #12
0
            private void DecodeElementaryStream(BitSplitter bs)
            {
                int marker = (int)bs.GetInteger(2);

                if (marker != 2)
                {
                    throw new DemuxException("Invalid PES: first marker missing");
                }
                ReadFlags(bs);
                if (bs.BitOffset != 0)
                {
                    throw new DemuxException("Alignment problem in PES (internal)");
                }
                HeaderLength = (int)bs.GetInteger(8);

                int head_start = bs.ByteOffset;

                if (HasPTS && HasDTS)
                {
                    ReadDTS_PTS(bs);
                }
                else if (HasPTS)
                {
                    ReadPTS(bs);
                }

                if (HasESCR)
                {
                    bs.SkipBytes(6);                          // not currently used.
                }
                if (HasEsRate)
                {
                    bs.SkipBits(24);                            // not currently used.
                }
                if (UsesTrickMode)
                {
                    bs.SkipBytes(1);                                // ignored
                }
                if (MoreCopyright)
                {
                    bs.SkipBytes(1);                                // ignored
                }
                if (HasPesCRC)
                {
                    bs.SkipBytes(2);                            // ignored
                }
                if (HasPesExtension)
                {
                    ReadExtendedHeader(bs);
                }

                // skip anything that's left
                int head_end = bs.ByteOffset;
                int to_skip  = HeaderLength - (head_end - head_start);

                if (to_skip < 0)
                {
                    throw new DemuxException("Invalid PES: declared header length did not match measured length");
                }
                bs.SkipBytes(to_skip);

                // Now, the remaining bytes are data and padding
                int data_length = PacketLength - (HeaderLength + to_skip);

                if (data_length > 3)
                {
                    data_length -= 3;                                  // no idea where the '3' is coming from...
                }
                byte[] data = bs.RemainingBytes();

                if (PacketLength == 0)                   // video is allowed to not specify
                {
                    data_length = data.Length;
                }

#if DEBUG
                if (data.Length < data_length)
                {
                    throw new DemuxException("Invalid PES: packet shorter than described");
                }

                if (data_length < 0)
                {
                    throw new DemuxException("Invalid PES: Negative packet length");
                }
#else
                if (data.Length < data_length || data_length < 0)
                {
                    data_length = 0;
                }
#endif

                MemoryStream ms = new MemoryStream(data, 0, data_length);
                FrameData = ms.ToArray();
            }
Пример #13
0
            /// <summary>
            /// Digest a packet payload into structured table. Payload should be from the pointer field onward.
            /// Does not yet handle multi-packet tables
            /// </summary>
            public PMT(byte[] RawPayload)
            {
                BitSplitter bs = new BitSplitter(RawPayload);

                Map        = new Dictionary <int, int>();
                ReverseMap = new Dictionary <StreamType, int>();

                ValidateTable(bs);

                bs.SkipBits(2);
                SectionLength = (int)bs.GetInteger(12);                 // total length after this, in bytes; includes 4 byte CRC.
                ProgramNumber = (int)bs.GetInteger(16);
                bs.SkipBits(2);

                Version       = (int)bs.GetInteger(5);
                IsCurrent     = bs.GetFlag();
                SectionNumber = (int)bs.GetInteger(8);
                LastSection   = (int)bs.GetInteger(8);
                bs.SkipBits(3);
                PCR_PID = (int)bs.GetInteger(13);                 // Either the PID of a channel timecode stream, or 0x1FFF for none.
                bs.SkipBits(4);

                ProgInfoLength = (int)bs.GetInteger(12);                 // number of bytes of descriptors.
                if (bs.BitOffset != 0)
                {
                    throw new DemuxException("Byte alignment error (internal)");
                }
                bs.SkipBytes(ProgInfoLength);                           // ignore descriptors.

                int info_bytes = (SectionLength - ProgInfoLength) - 13; // bytes of descriptor.

                while (info_bytes > 0)                                  // descriptions can be variable length
                {
                    int stream_type = (int)bs.GetInteger(8);
                    bs.SkipBits(3);
                    int pid = (int)bs.GetInteger(13);
                    bs.SkipBits(4);

                    if (!Map.ContainsKey(pid))
                    {
                        Map.Add(pid, stream_type);                                            // more complete map of pid types
                    }
                    else
                    {
                        throw new DemuxException("Invalid PMT: PID specified more than once");
                    }

                    StreamType st = DecodeStreamType(stream_type);
                    if (!ReverseMap.ContainsKey(st))
                    {
                        ReverseMap.Add(st, pid);                                                  // store first pid of each type
                    }
                    int es_info_length = (int)bs.GetInteger(12);
                    bs.SkipBytes(es_info_length);
                    info_bytes -= 5 + es_info_length;
                }
                if (bs.BitOffset != 0)
                {
                    throw new DemuxException("Invalid PMT: program info length didn't match data");
                }

                // ignoring CRC.
            }
Пример #14
0
        /// <summary>
        /// Двойное шифрование по алгоритму Rijndael-256
        /// </summary>
        /// <param name="inputStream">Входной поток.</param>
        /// <param name="key1">Ключ для первого прохода шифрования.</param>
        /// <param name="key2">Ключ для второго прохода шифрования.</param>
        /// <param name="outputStream">Выходной поток.</param>
        /// <param name="encryptionMode">Используется шифрование?</param>
        /// <param name="iterations">Количество итераций хеширования пароля.</param>
        public void DoubleRijndael(Stream inputStream, byte[] key1, byte[] key2, Stream outputStream, bool encryptionMode, int iterations = 1)
        {
            if(!inputStream.CanSeek)
            {
                throw new Exception("Cryforce::DoubleRijndael() ==> Input stream can't seek!");
            }

            var streamCryptoWrappers = new[] {new StreamCryptoWrapper(), new StreamCryptoWrapper()};
            streamCryptoWrappers[0].Initialize(encryptionMode ? key1 : key2, iterations); // При шифровании прямой порядок паролей...
            streamCryptoWrappers[1].Initialize(encryptionMode ? key2 : key1, iterations); // ...а при расшифровке - обратный

            // Генерируем 10 случайных имен файлов: два для целей временного хранения данных в пределах данного метода
            // и 8 штук для битсплиттера (генерируем их совместно, чтобы избежать конфликтов)
            string[] tempFilenamesAll = WorkInTempDir ? CryforceUtilities.GetTempFilenames(10) : CryforceUtilities.GetRandomFilenames(10, 8, RndSeed).Select(item => item + ".jpg").ToArray();
            var tempFilenames = new string[2];
            var tempFilenamesToBitSplitter = new string[8];
            Array.Copy(tempFilenamesAll, 0, tempFilenames, 0, 2);
            Array.Copy(tempFilenamesAll, 2, tempFilenamesToBitSplitter, 0, 8);

            Stream[] randomFilenameStreams = tempFilenames.Select(item => CryforceUtilities.PrepareOutputStream(ProgressChanged, item, BufferSizePerStream, ZeroOut, WorkInMemory, RndSeed)).ToArray();

            //////////////////////////////////////
            // Шифрование первого уровня (Level0)
            //////////////////////////////////////
            Stream inputStreamAtLevel0 = encryptionMode ? inputStream : streamCryptoWrappers[0].WrapStream(inputStream, false);
            Stream outputStreamAtLevel0 = encryptionMode ? streamCryptoWrappers[0].WrapStream(randomFilenameStreams[0], true) : randomFilenameStreams[0];

            inputStreamAtLevel0.SafeSeekBegin();
            outputStreamAtLevel0.SafeSeekBegin();

            // Процесс шифрования/расшифровки происходит прозрачно, во время чтения из зашифрованного потока или записи в зашифрованный
            // Размер буфера при копировании выбираем таким, чтобы обеспечить вывод каждого процента
            long dataSize = inputStream.Length;
            var bufferSize = (int)(dataSize / 100);
            CryforceUtilities.StreamCopy(ProgressChanged, inputStreamAtLevel0, outputStreamAtLevel0, dataSize, bufferSize);

            if(outputStreamAtLevel0 is CryptoStream)
            {
                ((CryptoStream)outputStreamAtLevel0).FlushFinalBlock();
            }
            outputStreamAtLevel0.Flush();

            // Если выходной поток первого уровня является криптографической оберткой над другим потоком -
            // нужно получить базовый поток для дальнейшей работы
            if(outputStreamAtLevel0 is CryptoStream)
            {
                outputStreamAtLevel0 = randomFilenameStreams[0];
            }

            inputStreamAtLevel0.SafeSeekBegin();
            outputStreamAtLevel0.SafeSeekBegin();

            if(ProgressChanged != null)
            {
                ProgressChanged(null, new EventArgsGeneric<ProgressChangedArg>(new ProgressChangedArg("Rijndael-256 (1/2)", 100)));
            }

            ////////////////////////////////////////////////////////
            // Перестановка битов посредством битсплиттера (Level1)
            ////////////////////////////////////////////////////////

            // Выходной поток первого уровня обработки является входным потоком для второго
            Stream inputStreamAtLevel1 = outputStreamAtLevel0;

            // Т.к. результат работы битсплиттера не является конечным - работаем с временным потоком
            Stream outputStreamAtLevel1 = randomFilenameStreams[1];

            inputStreamAtLevel1.SafeSeekBegin();
            outputStreamAtLevel1.SafeSeekBegin();

            var bitSplitter = new BitSplitter(tempFilenamesToBitSplitter, key1, key2, WorkInMemory);
            bitSplitter.RndSeed = RndSeed; // Некритичный параметр, но проброска значения желательна
            bitSplitter.ProgressChanged += ProgressChanged;
            if(encryptionMode)
            {
                bitSplitter.SplitToBitstream(inputStreamAtLevel1, outputStreamAtLevel1);
            }
            else
            {
                bitSplitter.UnsplitFromBitstream(inputStreamAtLevel1, outputStreamAtLevel1);
            }

            if(ProgressChanged != null)
            {
                ProgressChanged(null, new EventArgsGeneric<ProgressChangedArg>(new ProgressChangedArg("BitSplitter", 100)));
            }

            bitSplitter.ClearAndClose();

            inputStreamAtLevel1.SafeSeekBegin();
            outputStreamAtLevel1.SafeSeekBegin();

            //////////////////////////////////////
            // Шифрование второго уровня (Level2)
            //////////////////////////////////////
            Stream inputStreamAtLevel2 = encryptionMode ? outputStreamAtLevel1 : streamCryptoWrappers[1].WrapStream(outputStreamAtLevel1, false);
            Stream outputStreamAtLevel2 = encryptionMode ? streamCryptoWrappers[1].WrapStream(outputStream, true) : outputStream;

            inputStreamAtLevel2.SafeSeekBegin();
            outputStreamAtLevel2.SafeSeekBegin();

            // Процесс шифрования/расшифровки происходит прозрачно, во время чтения из зашифрованного потока или записи в зашифрованный
            // Размер буфера при копировании выбираем таким, чтобы обеспечить вывод каждого процента
            dataSize = outputStreamAtLevel1.Length;
            bufferSize = (int)(dataSize / 100);
            CryforceUtilities.StreamCopy(ProgressChanged, inputStreamAtLevel2, outputStreamAtLevel2, dataSize, bufferSize);

            if(outputStreamAtLevel2 is CryptoStream)
            {
                ((CryptoStream)outputStreamAtLevel2).FlushFinalBlock();
            }
            outputStreamAtLevel2.Flush();

            inputStreamAtLevel2.SafeSeekBegin();
            outputStreamAtLevel2.SafeSeekBegin();

            if(ProgressChanged != null)
            {
                ProgressChanged(null, new EventArgsGeneric<ProgressChangedArg>(new ProgressChangedArg("Rijndael-256 (2/2)", 100)));
            }

            // Уничтожаем данные временных потоков
            foreach(Stream randomFilenameStream in randomFilenameStreams)
            {
                CryforceUtilities.WipeStream(ProgressChanged, randomFilenameStream, BufferSizePerStream, 0, randomFilenameStream.Length, ZeroOut, RndSeed);
                randomFilenameStream.Flush();
                randomFilenameStream.Close();
            }

            // Производим удаление носителей
            foreach(string tempFilename in tempFilenames)
            {
                if(File.Exists(tempFilename))
                {
                    File.SetAttributes(tempFilename, FileAttributes.Normal);
                    File.Delete(tempFilename);
                }
            }

            // Закрываем все потоки, которые не являлись синонимами входа или выхода
            inputStreamAtLevel1.Close();
            inputStreamAtLevel2.Close();

            outputStreamAtLevel0.Close();
            outputStreamAtLevel1.Close();
        }