示例#1
0
        partial void ProcessEachInitIvExpand2(InitIvExpand2 initIvExpand2)
        {
            packetHandler.ReceivedFinalInitAck();

            var(publicKey, privateKey) = TsCrypt.GenerateTemporaryKey();

            var ekBase64 = Convert.ToBase64String(publicKey);
            var toSign   = new byte[86];

            Array.Copy(publicKey, 0, toSign, 0, 32);
            var beta = Convert.FromBase64String(initIvExpand2.Beta);

            Array.Copy(beta, 0, toSign, 32, 54);
            var sign  = TsCrypt.Sign(connectionDataFull.Identity.PrivateKey, toSign);
            var proof = Convert.ToBase64String(sign);

            ClientEk(ekBase64, proof);

            var result = tsCrypt.CryptoInit2(initIvExpand2.License, initIvExpand2.Omega, initIvExpand2.Proof, initIvExpand2.Beta, privateKey);

            if (!result)
            {
                DisconnectInternal(context, CommandError.Custom($"Failed to calculate shared secret: {result.Error}"));
                return;
            }

            DefaultClientInit();
        }
示例#2
0
        async partial void ProcessEachInitIvExpand2(InitIvExpand2 initIvExpand2)
        {
            var ctx = context;

            if (ctx is null)
            {
                throw new InvalidOperationException("context should be set");
            }

            ctx.PacketHandler.ReceivedFinalInitAck();

            var(publicKey, privateKey) = TsCrypt.GenerateTemporaryKey();

            var ekBase64 = Convert.ToBase64String(publicKey);
            var toSign   = new byte[86];

            Array.Copy(publicKey, 0, toSign, 0, 32);
            var beta = Convert.FromBase64String(initIvExpand2.Beta);

            Array.Copy(beta, 0, toSign, 32, 54);
            var sign  = TsCrypt.Sign(ctx.ConnectionDataFull.Identity.PrivateKey, toSign);
            var proof = Convert.ToBase64String(sign);

            await ClientEk(ekBase64, proof);

            var result = ctx.TsCrypt.CryptoInit2(initIvExpand2.License, initIvExpand2.Omega, initIvExpand2.Proof, initIvExpand2.Beta, privateKey);

            if (!result)
            {
                ChangeState(ctx, TsClientStatus.Disconnected, CommandError.Custom($"Failed to calculate shared secret: {result.Error}"));
                return;
            }

            await DefaultClientInit(ctx);
        }
示例#3
0
        public static bool IsUidValid(string uid)
        {
            if (uid == "anonymous" || uid == "serveradmin")
            {
                return(true);
            }
            var result = TsCrypt.Base64Decode(uid);

            return(result.Ok && result.Value.Length == 20);
        }
示例#4
0
        public PacketHandler(TsCrypt ts3Crypt, Id id)
        {
            receiveQueueCommand       = new RingQueue <Packet <TIn> >(ReceivePacketWindowSize, ushort.MaxValue + 1);
            receiveQueueCommandLow    = new RingQueue <Packet <TIn> >(ReceivePacketWindowSize, ushort.MaxValue + 1);
            receiveWindowVoice        = new GenerationWindow(ushort.MaxValue + 1);
            receiveWindowVoiceWhisper = new GenerationWindow(ushort.MaxValue + 1);

            NetworkStats = new NetworkStats();

            packetCounter     = new ushort[TsCrypt.PacketTypeKinds];
            generationCounter = new uint[TsCrypt.PacketTypeKinds];
            this.tsCrypt      = ts3Crypt;
            this.id           = id;
        }
示例#5
0
        /// <summary>Tries to connect to a server.</summary>
        /// <param name="conData">Set the connection information properties as needed.
        /// For further details about each setting see the respective property documentation in <see cref="ConnectionData"/></param>
        /// <exception cref="ArgumentException">When some required values are not set or invalid.</exception>
        /// <exception cref="TsException">When the connection could not be established.</exception>
        public override void Connect(ConnectionData conData)
        {
            if (!(conData is ConnectionDataFull conDataFull))
            {
                throw new ArgumentException($"Use the {nameof(ConnectionDataFull)} derivative to connect with the full client.", nameof(conData));
            }
            if (conDataFull.Identity is null)
            {
                throw new ArgumentNullException(nameof(conDataFull.Identity));
            }
            if (conDataFull.VersionSign is null)
            {
                throw new ArgumentNullException(nameof(conDataFull.VersionSign));
            }
            connectionDataFull = conDataFull;
            ConnectionData     = conData;

            Disconnect();

            if (!TsDnsResolver.TryResolve(conData.Address, out remoteAddress))
            {
                throw new TsException("Could not read or resolve address.");
            }

            lock (statusLock)
            {
                returnCode = 0;
                status     = TsClientStatus.Connecting;

                VersionSign      = conDataFull.VersionSign;
                tsCrypt          = new TsCrypt();
                tsCrypt.Identity = conDataFull.Identity;

                var ctx = new ConnectionContext {
                    WasExit = false
                };
                context = ctx;

                packetHandler             = new PacketHandler <S2C, C2S>(tsCrypt, conData.LogId);
                packetHandler.PacketEvent = (ref Packet <S2C> packet) => { PacketEvent(ctx, ref packet); };
                packetHandler.StopEvent   = (closeReason) => { ctx.ExitReason = closeReason; DisconnectInternal(ctx, setStatus: TsClientStatus.Disconnected); };
                packetHandler.Connect(remoteAddress);
                dispatcher = new ExtraThreadEventDispatcher();
                dispatcher.Init(InvokeEvent, conData.LogId);
            }
        }
示例#6
0
 public bool CheckValid() => TsCrypt.EdCheck(this);
示例#7
0
 public IdentityData(BigInteger privateKey, ECPoint publicKey = null)
 {
     PrivateKey = privateKey ?? throw new ArgumentNullException(nameof(privateKey));
     PublicKey  = publicKey ?? TsCrypt.RestorePublicFromPrivateKey(privateKey);
 }
示例#8
0
        public static R <(LicenseBlock block, int read), string> Parse(ReadOnlySpan <byte> data)
        {
            if (data.Length < MinBlockLen)
            {
                return("License too short");
            }
            if (data[0] != 0)
            {
                return($"Wrong key kind {data[0]} in license");
            }

            LicenseBlock block;
            int          read;

            switch (data[33])
            {
            case 0:
                var result = ReadNullString(data.Slice(46));
                if (!result.Ok)
                {
                    return(result.Error);
                }
                var nullStr = result.Value;
                block = new IntermediateLicenseBlock {
                    Issuer = nullStr.str
                };
                read = 5 + nullStr.read;
                break;

            case 2:
                if (!Enum.IsDefined(typeof(ServerLicenseType), data[42]))
                {
                    return($"Unknown license type {data[42]}");
                }
                result = ReadNullString(data.Slice(47));
                if (!result.Ok)
                {
                    return(result.Error);
                }
                nullStr = result.Value;
                block   = new ServerLicenseBlock {
                    Issuer = result.Value.str, LicenseType = (ServerLicenseType)data[42]
                };
                read = 6 + nullStr.read;
                break;

            case 32:
                block = new EphemeralLicenseBlock();
                read  = 0;
                break;

            default:
                return($"Invalid license block type {data[33]}");
            }

            block.NotValidBefore = Tools.UnixTimeStart.AddSeconds(BinaryPrimitives.ReadUInt32BigEndian(data.Slice(34)) + 0x50e22700uL);
            block.NotValidAfter  = Tools.UnixTimeStart.AddSeconds(BinaryPrimitives.ReadUInt32BigEndian(data.Slice(38)) + 0x50e22700uL);
            if (block.NotValidAfter < block.NotValidBefore)
            {
                return("License times are invalid");
            }

            block.Key = data.Slice(1, 32).ToArray();

            var allLen = MinBlockLen + read;
            var hash   = TsCrypt.Hash512It(data.Slice(1, allLen - 1).ToArray());

            block.Hash = hash.AsSpan(0, 32).ToArray();

            return(block, allLen);
        }