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()); }
public void Setup() { cryptoChannelStore = new CryptoDtoChannelStore(); cryptoChannelStore.CreateChannel("Benchmark"); var dto = new BenchmarkDto() { Callsign = "Benchmark", SequenceCounter = 0, Audio = new byte[200], LastPacket = false }; Random rnd = new Random(); rnd.NextBytes(dto.Audio); MemoryStream ms = new MemoryStream(); MessagePackSerializer.Serialize(ms, dto); cryptoChannelStore.TryGetChannel("Benchmark", out var channel); var config = channel.GetRemoteEndpointChannelConfig(); remoteChannel = new CryptoDtoChannel(config); cryptoDtoPacket = serializer.Serialize(cryptoChannelStore, "Benchmark", CryptoDtoMode.ChaCha20Poly1305, dto); }
// 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 CreateCryptoChannels() { if (Tokens == null) { throw new Exception(nameof(Tokens) + " not set"); } VoiceCryptoChannel = new CryptoDtoChannel(Tokens.VoiceServer.ChannelConfig); //DataCryptoChannel = new CryptoDtoChannel(Tokens.DataServer.ChannelConfig); }
//[Obsolete] //public byte[] Pack(CryptoDtoChannelStore channelStore, string channelTag, CryptoDtoMode mode, ReadOnlySpan<byte> dtoNameBuffer, ReadOnlySpan<byte> dtoBuffer) //{ // var channel = channelStore.GetChannel(channelTag); // return Pack(channel, mode, dtoNameBuffer, dtoBuffer); //} //[Obsolete] //public byte[] Pack(CryptoDtoChannel channel, CryptoDtoMode mode, ReadOnlySpan<byte> dtoNameBuffer, ReadOnlySpan<byte> dtoBuffer) //{ // ArrayBufferWriter<byte> arrayBufferWriter = new ArrayBufferWriter<byte>(); // Pack(arrayBufferWriter, channel, mode, dtoNameBuffer, dtoBuffer); // return arrayBufferWriter.WrittenSpan.ToArray(); //} 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); }
public static long SerialiseCryptoDto <T>(this DealerSocket dealerSocket, object data, CryptoDtoChannel channel, CryptoDtoMode mode) { T typedData = (T)data; byte[] cryptoData = CryptoDtoSerializer.Serialize(channel, mode, typedData); dealerSocket .SendMoreFrameEmpty() .SendFrame(cryptoData); return(cryptoData.Length); }
public static byte[] Pack(CryptoDtoChannel channel, CryptoDtoMode mode, byte[] dtoNameBuffer, byte[] dtoBuffer) { var transmitKey = channel.GetTransmitKey(mode, out ulong sequenceToSend); return(Pack(channel.ChannelTag, mode, transmitKey, sequenceToSend, dtoNameBuffer, dtoBuffer)); }
public static byte[] Serialize <T>(CryptoDtoChannel channel, CryptoDtoMode mode, T obj) { var transmitKey = channel.GetTransmitKey(mode, out ulong sequenceToSend); return(Serialise(channel.ChannelTag, mode, transmitKey, sequenceToSend, obj)); }
internal Deserializer(CryptoDtoChannel channel, ReadOnlySpan <byte> bytes, bool ignoreSequence) { sequenceValid = false; headerLength = Unsafe.ReadUnaligned <ushort>(ref MemoryMarshal.GetReference(bytes)); //.NET Standard 2.0 doesn't have BitConverter.ToUInt16(Span<T>) if (bytes.Length < (2 + headerLength)) { throw new CryptographicException("Not enough bytes to process packet."); } ReadOnlySpan <byte> headerBuffer = bytes.Slice(2, headerLength); header = MessagePackSerializer.Deserialize <CryptoDtoHeaderDto>(headerBuffer.ToArray()); if (header.ChannelTag != channel.ChannelTag) { throw new CryptographicException("Channel Tag doesn't match provided Channel"); } switch (header.Mode) { case CryptoDtoMode.ChaCha20Poly1305: { int aeLength = bytes.Length - (2 + headerLength); ReadOnlySpan <byte> aePayloadBuffer = bytes.Slice(2 + headerLength, aeLength); ReadOnlySpan <byte> adBuffer = bytes.Slice(0, 2 + headerLength); Span <byte> nonceBuffer = stackalloc byte[Aead.NonceSize]; BinaryPrimitives.WriteUInt64LittleEndian(nonceBuffer.Slice(4), header.Sequence); ReadOnlySpan <byte> receiveKey = channel.GetReceiveKey(header.Mode); var aead = new ChaCha20Poly1305(receiveKey.ToArray()); ReadOnlySpan <byte> decryptedPayload = aead.Decrypt(aePayloadBuffer.ToArray(), adBuffer.ToArray(), nonceBuffer); 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; } dtoNameLength = Unsafe.ReadUnaligned <ushort>(ref MemoryMarshal.GetReference(decryptedPayload)); //.NET Standard 2.0 doesn't have BitConverter.ToUInt16(Span<T>) if (decryptedPayload.Length < (2 + dtoNameLength)) { throw new CryptographicException("Not enough bytes to process packet. (2) " + dtoNameLength + " " + decryptedPayload.Length); } dtoNameBuffer = decryptedPayload.Slice(2, dtoNameLength); dataLength = Unsafe.ReadUnaligned <ushort>(ref MemoryMarshal.GetReference(decryptedPayload.Slice(2 + dtoNameLength, 2))); //.NET Standard 2.0 doesn't have BitConverter.ToUInt16(Span<T>) if (decryptedPayload.Length < (2 + dtoNameLength + 2 + dataLength)) { throw new CryptographicException("Not enough bytes to process packet. (3) " + dataLength + " " + decryptedPayload.Length); } dataBuffer = decryptedPayload.Slice(2 + dtoNameLength + 2, dataLength); break; } default: throw new CryptographicException("Mode not recognised"); } }
public static Deserializer DeserializeIgnoreSequence(CryptoDtoChannel channel, ReadOnlySpan <byte> bytes) //This is used for UDP channels where duplication is possible { return(new Deserializer(channel, bytes, true)); }
public static Deserializer Deserialize(CryptoDtoChannel channel, ReadOnlySpan <byte> bytes) { return(new Deserializer(channel, bytes, false)); }