示例#1
0
        public byte[] Serialize <T>(CryptoDtoChannel channel, CryptoDtoMode mode, T obj)
        {
            ArrayBufferWriter <byte> arrayBufferWriter = new ArrayBufferWriter <byte>();

            Serialize(arrayBufferWriter, channel, mode, obj);
            return(arrayBufferWriter.WrittenSpan.ToArray());
        }
示例#2
0
            internal Deserializer(CryptoDtoChannel channel, ushort headerLength, CryptoDtoHeaderDto header, ReadOnlySpan <byte> bytes, bool ignoreSequence, IBufferWriter <byte> plaintextBuffer)
            {
                sequenceValid = false;
                channelTag    = header.ChannelTag;

                switch (header.Mode)
                {
                case CryptoDtoMode.ChaCha20Poly1305:
                {
                    int adLength            = 2 + headerLength;
                    int aeLength            = bytes.Length - adLength - 16;
                    ReadOnlySpan <byte> ad  = bytes.Slice(0, adLength);
                    ReadOnlySpan <byte> ae  = bytes.Slice(adLength, aeLength);
                    ReadOnlySpan <byte> tag = bytes.Slice(adLength + aeLength, 16);

                    Span <byte> nonce = stackalloc byte[Aead.NonceSize];
                    BinaryPrimitives.WriteUInt64LittleEndian(nonce.Slice(4), header.Sequence);

                    var aead = channel.ReceiveChaCha20Poly1305;

                    Memory <byte> plaintext = plaintextBuffer.GetMemory(aeLength).Slice(0, aeLength);
                    aead.Decrypt(nonce, ae, tag, plaintext.Span, ad);

                    if (ignoreSequence)
                    {
                        sequenceValid = channel.IsReceivedSequenceAllowed(header.Sequence);
                    }
                    else
                    {
                        channel.CheckReceivedSequence(header.Sequence);             //The packet has passed MAC, so now check if it's being duplicated or replayed
                        sequenceValid = true;
                    }

                    var dtoNameLength = Unsafe.ReadUnaligned <ushort>(ref MemoryMarshal.GetReference(plaintext.Span));           //.NET Standard 2.0 doesn't have BitConverter.ToUInt16(Span<T>)

                    if (plaintext.Length < (2 + dtoNameLength))
                    {
                        throw new CryptographicException("Not enough bytes to process packet. (2) " + dtoNameLength + " " + plaintext.Length);
                    }

                    dtoNameBuffer = plaintext.Span.Slice(2, dtoNameLength);

                    var dtoLength = Unsafe.ReadUnaligned <ushort>(ref MemoryMarshal.GetReference(plaintext.Span.Slice(2 + dtoNameLength, 2)));           //.NET Standard 2.0 doesn't have BitConverter.ToUInt16(Span<T>)

                    if (plaintext.Length < (2 + dtoNameLength + 2 + dtoLength))
                    {
                        throw new CryptographicException("Not enough bytes to process packet. (3) " + dtoLength + " " + plaintext.Length);
                    }
                    dtoBuffer = plaintext.Slice(2 + dtoNameLength + 2, dtoLength);
                    break;
                }

                default:
                    throw new CryptographicException("Mode not recognised");
                }
            }
示例#3
0
        public static Deserializer Deserialize(IBufferWriter <byte> plaintextBuffer, CryptoDtoChannel channel, ReadOnlyMemory <byte> bytes)
        {
            var header = Deserializer.GetHeader(bytes, out ushort headerLength);

            if (header.ChannelTag != channel.ChannelTag)
            {
                throw new CryptographicException("Channel Tag doesn't match provided Channel");
            }
            return(new Deserializer(channel, headerLength, header, bytes.Span, false, plaintextBuffer));
        }
示例#4
0
 // Hint for callers using ArrayBufferWriter<byte> - output.WrittenSpan contains the serialised data
 public void Serialize <T>(IBufferWriter <byte> output, CryptoDtoChannel channel, CryptoDtoMode mode, T dto)
 {
     lock (bufferLock)
     {
         ReadOnlySpan <byte> dtoNameBuffer = GetDtoNameBytes <T>();
         dtoBuffer.Clear();
         MessagePackSerializer.Serialize(dtoBuffer, dto);
         Pack(output, channel, mode, dtoNameBuffer, dtoBuffer.WrittenSpan);
     }
 }
 public void CreateChannel(string channelTag, int receiveSequenceHistorySize = 10)
 {
     lock (channelStoreLock)
     {
         if (channelStore.ContainsKey(channelTag))
         {
             throw new CryptographicException("Key tag already exists in store. (" + channelTag + ")");
         }
         channelStore[channelTag] = new CryptoDtoChannel(channelTag, receiveSequenceHistorySize);
     }
 }
示例#6
0
 public bool TryCreateChannel(string channelTag, int receiveSequenceHistorySize = 10)
 {
     lock (channelStoreLock)
     {
         if (channelStore.ContainsKey(channelTag))
         {
             return(false);
         }
         channelStore[channelTag] = new CryptoDtoChannel(channelTag, receiveSequenceHistorySize);
         return(true);
     }
 }
示例#7
0
        public void Pack(IBufferWriter <byte> output, CryptoDtoChannel channel, CryptoDtoMode mode, ReadOnlySpan <byte> dtoNameBuffer, ReadOnlySpan <byte> dtoBuffer)
        {
            channel.GetTransmitKey(mode, out ulong sequenceToSend);
            CryptoDtoHeaderDto header = new CryptoDtoHeaderDto
            {
                ChannelTag = channel.ChannelTag,
                Mode       = mode,
                Sequence   = sequenceToSend
            };

            Pack(output, header, channel.TransmitChaCha20Poly1305, dtoNameBuffer, dtoBuffer);
        }
示例#8
0
        public bool TryGetChannel(string channelTag, out CryptoDtoChannel channel)
        {
            lock (channelStoreLock)
            {
                if (!channelStore.ContainsKey(channelTag))
                {
                    channel = null;
                    return(false);
                }

                channel = channelStore[channelTag];
                return(true);
            }
        }
示例#9
0
        public static Deserializer DeserializeIgnoreSequence(IBufferWriter <byte> plaintextBuffer, CryptoDtoChannel channel, ReadOnlyMemory <byte> bytes)            //This is used for UDP channels where duplication is possible and the overhead of CryptographicException isn't acceptable. Use IsSequenceValid() in code to ignore the UDP packet.
        {
            var header = Deserializer.GetHeader(bytes, out ushort headerLength);

            if (header.ChannelTag != channel.ChannelTag)
            {
                throw new CryptographicException("Channel Tag doesn't match provided Channel");
            }
            return(new Deserializer(channel, headerLength, header, bytes.Span, true, plaintextBuffer));
        }
示例#10
0
        public static Deserializer DeserializeIgnoreSequence(CryptoDtoChannel channel, ReadOnlyMemory <byte> bytes)            //This is used for UDP channels where duplication is possible and the overhead of CryptographicException isn't acceptable. Use IsSequenceValid() in code to ignore the UDP packet.
        {
            var plaintextBuffer = new ArrayBufferWriter <byte>();

            return(DeserializeIgnoreSequence(plaintextBuffer, channel, bytes));
        }
示例#11
0
        public static Deserializer Deserialize(CryptoDtoChannel channel, ReadOnlyMemory <byte> bytes)
        {
            var plaintextBuffer = new ArrayBufferWriter <byte>();

            return(Deserialize(plaintextBuffer, channel, bytes));
        }