Example #1
0
        // For use with System.IO.Pipelines
        // Decrypt packets directly from underlying data stream without needing to buffer
        public int TryDecrypt(ReadOnlySequence <byte> buffer, out PoolPacketReader packet)
        {
            if (buffer.Length < HEADER_SIZE)
            {
                packet = null;
                return(0);
            }

            SequenceReader <byte> reader = new(buffer);

            reader.TryReadLittleEndian(out short encSeq);
            reader.TryReadLittleEndian(out int packetSize);
            int rawPacketSize = HEADER_SIZE + packetSize;

            if (buffer.Length < rawPacketSize)
            {
                packet = null;
                return(0);
            }

            // Only decode sequence once we know there is sufficient data because it mutates IV
            short decSeq = DecodeSeqBase(encSeq);

            if (decSeq != Cipher.Version)
            {
                throw new ArgumentException($"Packet has invalid sequence header: {decSeq}");
            }

            byte[] data = ArrayProvider.Rent(packetSize);
            buffer.Slice(HEADER_SIZE, packetSize).CopyTo(data);
            foreach (ICrypter crypter in DecryptSeq)
            {
                crypter.Decrypt(data, 0, packetSize);
            }

            packet = new(ArrayProvider, data, packetSize);
            return(rawPacketSize);
        }