/// <inheritdoc cref="IMessageReader.ReadFrom"/> public IMessage ReadFrom(ref SpanBufferReader bufferReader, byte packetProperty) { if (packetProperty != 0x00) { var readPacketProperty = bufferReader.ReadUInt8(); if (readPacketProperty != packetProperty) { throw new InvalidDataContractException( "Invalid packet property " + $"(PacketProperty={readPacketProperty}, Expected={packetProperty})." ); } } var messageGroup = bufferReader.ReadUInt32(); if (!_messageRegistries.TryGetValue(messageGroup, out var messageRegistry)) { throw new InvalidDataContractException($"Invalid message group (MessageGroup={messageGroup})."); } var protocolVersion = bufferReader.ReadVarUInt(); if (protocolVersion != ProtocolVersion) { throw new InvalidDataContractException($"Invalid message protocol version (ProtocolVersion={protocolVersion})."); } var length = bufferReader.ReadVarUInt(); if (bufferReader.RemainingSize < length) { throw new InvalidDataContractException($"Message truncated (RemainingSize={bufferReader.RemainingSize}, Expected={length})."); } var messageId = bufferReader.ReadVarUInt(); if (!messageRegistry.TryCreateMessage(messageId, out var message)) { throw new InvalidDataContractException($"Invalid message identifier (MessageId={messageId})."); } if (message is IReliableRequest) { ((IReliableRequest)message).RequestId = bufferReader.ReadUInt32(); } if (message is IReliableResponse) { ((IReliableResponse)message).ResponseId = bufferReader.ReadUInt32(); } message.ReadFrom(ref bufferReader); return(message); }
/// <inheritdoc cref="IEncryptedMessageReader.ReadFrom"/> public IEncryptedMessage ReadFrom(ref SpanBufferReader bufferReader, byte[] key, HMAC hmac, byte?packetProperty) { var sequenceId = bufferReader.ReadUInt32(); var iv = bufferReader.ReadBytes(16).ToArray(); var decryptedBuffer = bufferReader.RemainingData.ToArray(); using (var cryptoTransform = _aesCryptoServiceProvider.CreateDecryptor(key, iv)) { var bytesWritten = 0; for (var i = decryptedBuffer.Length; i >= cryptoTransform.InputBlockSize; i -= bytesWritten) { var inputCount = cryptoTransform.CanTransformMultipleBlocks ? (i / cryptoTransform.InputBlockSize * cryptoTransform.InputBlockSize) : cryptoTransform.InputBlockSize; bytesWritten = cryptoTransform.TransformBlock( decryptedBuffer, bytesWritten, inputCount, decryptedBuffer, bytesWritten ); } } var paddingByteCount = decryptedBuffer[decryptedBuffer.Length - 1] + 1; var hmacStart = decryptedBuffer.Length - paddingByteCount - 10; var decryptedBufferSpan = decryptedBuffer.AsSpan(); var hash = decryptedBufferSpan.Slice(hmacStart, 10); var hashBufferWriter = new SpanBufferWriter(stackalloc byte[decryptedBuffer.Length + 4]); hashBufferWriter.WriteBytes(decryptedBufferSpan.Slice(0, hmacStart)); hashBufferWriter.WriteUInt32(sequenceId); Span <byte> computedHash = stackalloc byte[32]; if (!hmac.TryComputeHash(hashBufferWriter.Data, computedHash, out _)) { throw new Exception("Failed to compute message hash."); } if (!hash.SequenceEqual(computedHash.Slice(0, 10))) { throw new Exception("Message hash does not match the computed hash."); } bufferReader = new SpanBufferReader(decryptedBuffer); if (_messageReader.ReadFrom(ref bufferReader, packetProperty) is not IEncryptedMessage message) { throw new Exception( "Successfully decrypted message but failed to cast to type " + $"'{nameof(IEncryptedMessage)}'." ); } message.SequenceId = sequenceId; return(message); }
public override void ReadFrom(ref SpanBufferReader bufferReader) { MultipartMessageId = bufferReader.ReadUInt32(); Offset = bufferReader.ReadVarUInt(); Length = bufferReader.ReadVarUInt(); TotalLength = bufferReader.ReadVarUInt(); if (Length > _maximumLength) { throw new InvalidDataContractException($"Length must not surpass {_maximumLength} bytes"); } if (TotalLength > _maximumTotalLength) { throw new InvalidDataContractException($"Length must not surpass {_maximumTotalLength} bytes"); } Data = bufferReader.ReadBytes((int)Length).ToArray(); }
public void ReadFrom(ref SpanBufferReader bufferReader) { CertificateResponseId = bufferReader.ReadUInt32(); Random = bufferReader.ReadBytes(32).ToArray(); Cookie = bufferReader.ReadBytes(32).ToArray(); }