示例#1
0
        public void TestByte()
        {
            _writer.Write((byte)0xFE);
            _writer.Write((byte)0xFA);

            Assert.Equal <byte[]>(new byte[] { 0xFE, 0xFA }, _writer.ToBytes());
        }
        /// <summary>
        /// Sends an auxiliary chunk.
        /// </summary>
        /// <returns>The async.</returns>
        /// <param name="bytes">Plaintext bytes.</param>
        public async Task SendAsync(byte[] bytes)
        {
            logger.LogTrace($"Sending auxiliary stream buffer: {bytes.Length} bytes");

            var writer = new EndianWriter();

            writer.Write(new byte[] { 0xde, 0xad });
            writer.WriteBE((ushort)bytes.Length);
            writer.Write(_cryptoContext.Encrypt(bytes));
            writer.Write(_cryptoContext.CalculateMessageSignature(writer.ToBytes()));

            var buffer = writer.ToBytes();

            await _client.GetStream().WriteAsync(buffer, 0, buffer.Length);
        }
        private byte[] AssembleMessage(IMessage message)
        {
            var writer = new EndianWriter();

            message.Serialize(writer);
            return(writer.ToBytes());
        }
        private byte[] AssembleSessionMessage(SessionMessageBase message,
                                              uint sequenceNumber,
                                              uint sourceParticipantId,
                                              uint targetParticipantId = 0)
        {
            var fragment = new SessionFragmentMessage();

            fragment.Header.IsFragment         = message.Header.IsFragment;
            fragment.Header.ChannelId          = message.Header.ChannelId;
            fragment.Header.RequestAcknowledge = message.Header.RequestAcknowledge;
            fragment.Header.SessionMessageType = message.Header.SessionMessageType;
            fragment.Header.Version            = message.Header.Version;

            fragment.Header.SequenceNumber      = sequenceNumber;
            fragment.Header.SourceParticipantId = sourceParticipantId;
            fragment.Header.TargetParticipantId = targetParticipantId;

            var writer = new EndianWriter();

            message.Serialize(writer);
            fragment.Fragment = writer.ToBytes();

            ((ICryptoMessage)fragment).Crypto = _crypto;

            var finalWriter = new EndianWriter();

            fragment.Serialize(finalWriter);
            return(finalWriter.ToBytes());
        }
        /// <summary>
        /// Sends a packet
        /// </summary>
        /// <returns>The send task.</returns>
        /// <param name="message">SmartGlass SimpleMessage to sent</param>
        public async Task SendAsync(IMessage message)
        {
            var cryptoMessage = message as ICryptoMessage;

            if (cryptoMessage != null)
            {
                cryptoMessage.Crypto = _crypto;
            }

            var writer = new EndianWriter();

            message.Serialize(writer);
            var serialized = writer.ToBytes();

            if (_addressOrHostname == null)
            {
                await _client.SendAsync(serialized, serialized.Length, new IPEndPoint(IPAddress.Broadcast, 5050));

                await _client.SendAsync(serialized, serialized.Length, new IPEndPoint(MULTICAST_ADDR, 5050));
            }
            else
            {
                await _client.SendAsync(serialized, serialized.Length);
            }
        }
示例#6
0
        public override void Serialize(EndianWriter writer)
        {
            var messageWriter = new EndianWriter();

            base.Serialize(messageWriter);

            var message = messageWriter.ToBytes();

            var initVectorSource = message.Take(16).ToArray();
            var initVector       = Crypto.CreateDerivedInitVector(initVectorSource);

            var fragmentWriter = new EndianWriter();

            byte[] padding = Padding.CreatePaddingData(
                PaddingType.PKCS7,
                Fragment,
                alignment: payloadSizeAlignment
                );

            fragmentWriter.Write(Fragment);
            fragmentWriter.Write(padding);

            var encryptedFragment = Crypto.EncryptWithoutPadding(fragmentWriter.ToBytes(), initVector);

            Header.Serialize(writer);
            writer.Write(encryptedFragment);

            var signature = Crypto.CalculateMessageSignature(writer.ToBytes());

            writer.Write(signature);
        }
示例#7
0
        public SessionMessageBase AssembleFragment(SessionMessageBase message, uint sequenceNumber)
        {
            FragmentMessage fragment = message as FragmentMessage;

            SessionMessageType messageType = fragment.Header.SessionMessageType;
            int sequenceBegin = (int)fragment.SequenceBegin;
            int sequenceEnd   = (int)fragment.SequenceEnd;

            _fragmentQueue[(int)sequenceNumber] = fragment.Data;

            IEnumerable <int> neededSequences = Enumerable.Range(sequenceBegin, sequenceEnd - sequenceBegin);

            foreach (var seq in neededSequences)
            {
                if (!_fragmentQueue.ContainsKey(seq))
                {
                    return(null);
                }
            }

            EndianWriter writer = new EndianWriter();

            foreach (int seq in neededSequences)
            {
                byte[] data = _fragmentQueue[seq];
                writer.Write(data);
                _fragmentQueue.Remove(seq);
            }

            SessionMessageBase assembled = SessionMessageTransport.CreateFromMessageType(messageType);

            assembled.Deserialize(new EndianReader(writer.ToBytes()));
            return(assembled);
        }
示例#8
0
        public override void Serialize(EndianWriter writer)
        {
            var protectedPayloadWriter = new EndianWriter();

            SerializeProtectedPayload(protectedPayloadWriter);

            // length is before padding
            Header.ProtectedPayloadLength = (ushort)protectedPayloadWriter.Length;

            // padding is before encryption
            byte[] padding = Padding.CreatePaddingData(
                PaddingType.PKCS7,
                protectedPayloadWriter.Length,
                alignment: payloadSizeAlignment
                );

            protectedPayloadWriter.Write(padding);

            // encrypt without adding padding to the encrypted value
            var encryptedPayload = Crypto.EncryptWithoutPadding(protectedPayloadWriter.ToBytes(), InitVector);

            base.Serialize(writer);
            writer.Write(encryptedPayload);

            var signature = Crypto.CalculateMessageSignature(writer.ToBytes());

            writer.Write(signature);
        }
        public virtual void Serialize(EndianWriter writer)
        {
            var payloadWriter = new EndianWriter();

            SerializePayload(payloadWriter);

            var payload = payloadWriter.ToBytes();

            Header.PayloadLength = (ushort)payload.Length;

            Header.Serialize(writer);
            writer.Write(payload);
        }
        public void Serialize(EndianWriter writer)
        {
            // Write out payload first to get its size
            EndianWriter tmpWriter = new EndianWriter();

            SerializeStreamer(tmpWriter);
            byte[] streamerData = tmpWriter.ToBytes();
            StreamerSize = (uint)streamerData.Length;

            StreamerHeader.Serialize(writer);
            writer.WriteLE(StreamerSize);
            writer.Write(streamerData);
        }
示例#11
0
        public static byte[] AssemblePacket(INanoPacket packet, NanoChannelContext context)
        {
            if (packet.Channel == NanoChannel.Unknown)
            {
                throw new NanoPackingException("AssemblePacket: INanoPacket.Channel is UNKNOWN");
            }

            // Serialize payload and append padding if needed
            byte[] payloadData = null;
            using (EndianWriter payloadWriter = new EndianWriter())
            {
                packet.Serialize(payloadWriter);
                byte[] padding = Padding.CreatePaddingData(
                    PaddingType.ANSI_X923,
                    payloadWriter.ToBytes(),
                    alignment: 4);

                // Append padding
                if (padding.Length > 0)
                {
                    payloadWriter.Write(padding);
                    packet.Header.Padding = true;
                }

                payloadData = payloadWriter.ToBytes();
            }

            EndianWriter packetWriter = new EndianWriter();

            packet.Header.ChannelId = context.GetChannelId(packet.Channel);

            // Serialize header
            packet.Header.Serialize(packetWriter);
            // Append payload to header
            packetWriter.Write(payloadData);

            return(packetWriter.ToBytes());
        }
示例#12
0
        private Task SendFragmentAsync(SessionMessageBase message, uint sequenceNumber)
        {
            var fragment = new SessionFragmentMessage();

            fragment.Header.ChannelId          = message.Header.ChannelId;
            fragment.Header.RequestAcknowledge = message.Header.RequestAcknowledge;
            fragment.Header.SessionMessageType = message.Header.SessionMessageType;
            fragment.Header.Version            = message.Header.Version;

            fragment.Header.SequenceNumber      = sequenceNumber;
            fragment.Header.SourceParticipantId = _participantId;

            var writer = new EndianWriter();

            message.Serialize(writer);
            fragment.Fragment = writer.ToBytes();

            return(_transport.SendAsync(fragment));
        }
        public override void Serialize(EndianWriter writer)
        {
            var protectedPayloadWriter = new EndianWriter();

            SerializeProtectedPayload(protectedPayloadWriter);

            var protectedPayload = protectedPayloadWriter.ToBytes();

            Header.ProtectedPayloadLength = (ushort)protectedPayload.Length;

            var encryptedPayload = protectedPayload.Length > 0 ?
                                   Crypto.Encrypt(protectedPayload, InitVector) : new byte[] { };

            base.Serialize(writer);
            writer.Write(encryptedPayload);

            var signature = Crypto.CalculateMessageSignature(writer.ToBytes());

            writer.Write(signature);
        }
        /// <summary>
        /// Reads and decrypts auxiliary channel chunk.
        /// </summary>
        /// <returns>Decrypted chunk.</returns>
        /// <param name="stream">Stream.</param>
        private byte[] ReadAndDecryptChunk(Stream stream)
        {
            var reader = new EndianReader(stream);

            // 0xde, 0xad
            reader.ReadBytes(2);

            var length = reader.ReadUInt16BE();

            var encryptedPayloadLength = length + Padding.CalculatePaddingSize(length, 16);

            var encryptedPayloadBytes    = new byte[encryptedPayloadLength];
            var encryptedPayloadPosition = 0;

            while (encryptedPayloadPosition < encryptedPayloadLength - 1)
            {
                var received = reader.ReadBytes(encryptedPayloadLength - encryptedPayloadPosition);
                received.CopyTo(encryptedPayloadBytes, encryptedPayloadPosition);
                encryptedPayloadPosition += received.Length;
            }

            var signature = reader.ReadBytes(32);

            var bodyWriter = new EndianWriter();

            bodyWriter.Write(new byte[] { 0xde, 0xad });
            bodyWriter.WriteBE(length);
            bodyWriter.Write(encryptedPayloadBytes);

            var messageSignature = _cryptoContext.CalculateMessageSignature(bodyWriter.ToBytes());

            if (!signature.SequenceEqual(messageSignature))
            {
                throw new InvalidDataException("Invalid message signature.");
            }

            var decryptedPayload = _cryptoContext.Decrypt(encryptedPayloadBytes);

            return(decryptedPayload.Take(length).ToArray());
        }
        /// <summary>
        /// Encrypt the specified data.
        /// </summary>
        /// <returns>The encrypted data</returns>
        /// <param name="data">Encrypted data.</param>
        public byte[] Encrypt(byte[] data)
        {
            var writer = new EndianWriter();

            byte[] padding = Padding.CreatePaddingData(
                PaddingType.PKCS7,
                data,
                alignment: 16);

            writer.Write(data);
            writer.Write(padding);

            var paddedData = writer.ToBytes();

            var output = new byte[paddedData.Length];

            for (var i = 0; i < paddedData.Length; i += 16)
            {
                _clientCipher.ProcessBlock(paddedData, i, output, i);
            }

            return(output);
        }
        /// <summary>
        /// Generates the connect request.
        /// Either returns a single ConnectRequest if no authorization data is
        /// provided or more-than-one if authorization data is provided.
        /// </summary>
        /// <returns>An Enumerable of connect requests.</returns>
        /// <param name="deviceId">Client device Id.</param>
        /// <param name="xboxLiveUserHash">Xbox live user hash.</param>
        /// <param name="xboxLiveAuthorization">Xbox live authorization token (XToken).</param>
        /// <param name="initialSequenceNumber">Initial sequence number.</param>
        public static IEnumerable <ConnectRequestMessage> GenerateConnectRequest(
            Guid deviceId, CryptoContext crypto,
            string xboxLiveUserHash, string xboxLiveAuthorization,
            int initialSequenceNumber = 0)
        {
            var requests = new List <ConnectRequestMessage>();

            /*
             * Get size of anonymous ConnectRequest to calculate
             * available space for authentication data
             */
            var          anonymousRequest = GenerateAnonymousRequest(deviceId, crypto, initialSequenceNumber);
            EndianWriter bw = new EndianWriter();

            ((ICryptoMessage)anonymousRequest).Crypto = crypto;
            anonymousRequest.Serialize(bw);
            var connectRequestSize = bw.ToBytes().Length;

            if (String.IsNullOrEmpty(xboxLiveAuthorization) ||
                String.IsNullOrEmpty(xboxLiveUserHash))
            {
                // Incomplete authoritzation data
                // Return anonymous connect request
                requests.Add(anonymousRequest);
                return(requests);
            }

            var authenticationStringLength = xboxLiveUserHash.Length
                                             + xboxLiveAuthorization.Length;
            var maxStringSize = 1024 - connectRequestSize;
            var fragmentCount = authenticationStringLength / maxStringSize;

            if ((authenticationStringLength % maxStringSize) > 0)
            {
                fragmentCount++;
            }

            if (fragmentCount <= 1)
            {
                throw new InvalidOperationException(
                          "Authentication data too small to fragment");
            }

            var xtokenPosition = 0;

            for (int fragment = 0; fragment < fragmentCount; fragment++)
            {
                var availableBytes  = maxStringSize;
                var currentUserhash = String.Empty;
                var currentXToken   = String.Empty;

                if (fragment == 0)
                {
                    // Userhash fits in first fragment
                    currentUserhash = xboxLiveUserHash;
                    availableBytes -= currentUserhash.Length;
                }

                var xtokenCopyLength = availableBytes > (xboxLiveAuthorization.Length - xtokenPosition)
                                       ? xboxLiveAuthorization.Length - xtokenPosition
                                       : availableBytes;

                currentXToken   = xboxLiveAuthorization.Substring(xtokenPosition, xtokenCopyLength);
                xtokenPosition += currentXToken.Length;

                var requestFragment = new ConnectRequestMessage()
                {
                    InitVector    = SmartGlass.Connection.CryptoContext.GenerateRandomInitVector(),
                    DeviceId      = deviceId,
                    UserHash      = currentUserhash,
                    Authorization = currentXToken,

                    SequenceNumber = (uint)(initialSequenceNumber + fragment),
                    SequenceBegin  = (uint)initialSequenceNumber,
                    SequenceEnd    = (uint)(initialSequenceNumber + fragmentCount)
                };
                requests.Add(requestFragment);
            }

            return(requests);
        }