Esempio n. 1
0
        public void TestSerialization()
        {
            var launchSpecs = LaunchSpecification.GetStandardSpecs(sessionId, handshakeKey);
            var assembled   = launchSpecs.Serialize();

            //Assert.Equal(expectedLaunchSpec.Length, assembled.Length);
            Assert.Equal(expectedLaunchSpec, assembled);
        }
        private RemotePlayContext SendBigBangMessages(Socket udpClient, Session session, RemotePlayContext remotePlayContext)
        {
            /******** Big Payload send ********/

            // Generate random handshake key, for ECDH pubkey signature calculation
            byte[] handshakeKey = new byte[16];
            new Random().NextBytes(handshakeKey);

            // Generate ECDH keypair
            var ecdhKeyPair = CryptoService.GenerateEcdhKeyPair();
            // Get public key bytes
            var ownPublicKey = Session.GetPublicKeyBytesFromKeyPair(ecdhKeyPair);

            // Calculate ECDH pubkey signature
            var ecdhSignature = Session.CalculateHMAC(handshakeKey, ownPublicKey);

            int    unixTimestamp = (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
            string timestampUnix = unixTimestamp.ToString();
            string sessionKey    = timestampUnix + CryptoService.GetUniqueKey(64);

            LaunchSpecification launchSpecs = LaunchSpecification.GetStandardSpecs("sessionId123", handshakeKey);

            byte[] launchSpecBuffer = Encoding.UTF8.GetBytes(launchSpecs.Serialize());

            byte[] cryptoBuffer = new byte[launchSpecBuffer.Length];
            cryptoBuffer = session.Encrypt(cryptoBuffer, 0);
            byte[] newLaunchSpec = new byte[launchSpecBuffer.Length];
            for (int i = 0; i < launchSpecBuffer.Length; i++)
            {
                newLaunchSpec[i] = (byte)(launchSpecBuffer[i] ^ cryptoBuffer[i]);
            }

            TakionMessage takionBigPayloadMessage = new TakionMessage
            {
                Type       = TakionMessage.PayloadType.Big,
                bigPayload = new BigPayload
                {
                    clientVersion = 9,
                    sessionKey    = sessionKey,
                    launchSpec    = Convert.ToBase64String(newLaunchSpec),
                    encryptedKey  = new byte[] { 0, 0, 0, 0 },
                    ecdhPubKey    = ownPublicKey,
                    ecdhSig       = ecdhSignature
                }
            };

            MemoryStream bigPayloadStream = new MemoryStream();

            Serializer.Serialize(bigPayloadStream, takionBigPayloadMessage);
            byte[] bigPayloadBuffer = ByteUtil.ConcatenateArrays(new byte[1], bigPayloadStream.ToArray()); // Padding byte + BigPayload
            ushort bigPayloadSize   = (ushort)(12 + bigPayloadBuffer.Length);

            ControlMessage controlMessageBigPayload = new ControlMessage(0, remotePlayContext.ReceiverId, 0, 0, 0, 1, bigPayloadSize, remotePlayContext.FuncIncr, 0x10000);

            controlMessageBigPayload.UnParsedPayload = bigPayloadBuffer;
            byte[] initialControlMessage2Data = GetByteArrayForControlMessage(controlMessageBigPayload);

            OnPs4LogInfo?.Invoke(this, Environment.NewLine + "Sending big payload:");
            OnPs4LogInfo?.Invoke(this, "ECDH pubkey: " + HexUtil.Hexlify(takionBigPayloadMessage.bigPayload.ecdhPubKey));
            OnPs4LogInfo?.Invoke(this, "ECDH sig: " + HexUtil.Hexlify(takionBigPayloadMessage.bigPayload.ecdhSig));
            OnPs4LogInfo?.Invoke(this, "Session key: " + takionBigPayloadMessage.bigPayload.sessionKey + Environment.NewLine);

            ControlResult bigPayloadResult = SendControlDataAndWaitForAnswer(udpClient, initialControlMessage2Data, 2, "Send BigPayload");

            if (!bigPayloadResult.WasSuccessful)
            {
                return(null);
            }

            /******** Bang Payload receive ********/

            ControlMessage answerPacket1 = bigPayloadResult.ControlMessages[0];
            ControlMessage answerPacket2 = bigPayloadResult.ControlMessages[1];

            if (answerPacket1.ProtoBuffFlag != 1 && answerPacket2.ProtoBuffFlag != 1)
            {
                return(null);
            }

            TakionMessage bangPayload = answerPacket1.ProtoBuffFlag == 1 ?
                                        Serializer.Deserialize <TakionMessage>(new MemoryStream(answerPacket1.UnParsedPayload)) :
                                        Serializer.Deserialize <TakionMessage>(new MemoryStream(answerPacket2.UnParsedPayload));

            if (bangPayload.bangPayload == null)
            {
                return(null);
            }

            ControlMessage bangPayloadControl = answerPacket1.ProtoBuffFlag == 1 ? answerPacket1 : answerPacket2;

            OnPs4LogInfo?.Invoke(this, Environment.NewLine + "Received bang payload:");
            OnPs4LogInfo?.Invoke(this, "ECDH pubkey: " + HexUtil.Hexlify(bangPayload.bangPayload.ecdhPubKey));
            OnPs4LogInfo?.Invoke(this, "ECDH sig: " + HexUtil.Hexlify(bangPayload.bangPayload.ecdhSig));
            OnPs4LogInfo?.Invoke(this, "Session key: " + bangPayload.bangPayload.sessionKey);

            /* Derive ECDH shared secret */
            var foreignPubkeyParams = Session.ConvertPubkeyBytesToCipherParams(bangPayload.bangPayload.ecdhPubKey);

            remotePlayContext.SharedSecret   = Session.GenerateSharedSecret(ecdhKeyPair.Private, foreignPubkeyParams);
            remotePlayContext.LocalGmacInfo  = CryptoService.SetUpGmac(2, handshakeKey, remotePlayContext.SharedSecret);
            remotePlayContext.RemoteGmacInfo = CryptoService.SetUpGmac(3, handshakeKey, remotePlayContext.SharedSecret);
            OnPs4LogInfo?.Invoke(this, "HANDSHAKE KEY: " + HexUtil.Hexlify(handshakeKey));
            OnPs4LogInfo?.Invoke(this, "SHARED SECRET: " + HexUtil.Hexlify(remotePlayContext.SharedSecret));

            byte[]         ackBangPayload        = HexUtil.Unhexlify("00000000");
            ushort         ackBangPayloadSize    = (ushort)(12 + ackBangPayload.Length);
            ControlMessage ackBangPayloadMessage = new ControlMessage(0, bangPayloadControl.FuncIncr, 0, 0, 3, 0, ackBangPayloadSize, bangPayloadControl.FuncIncr, 0x19000);

            ackBangPayloadMessage.UnParsedPayload = ackBangPayload;
            byte[] ackBangPayloadMessageData = GetByteArrayForControlMessage(ackBangPayloadMessage);
            remotePlayContext.LastSentMessage = ackBangPayloadMessageData;

            SendData(udpClient, ackBangPayloadMessageData);

            return(remotePlayContext);
        }