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(); }
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); }
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); }
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; }
/// <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); } }
public bool CheckValid() => TsCrypt.EdCheck(this);
public IdentityData(BigInteger privateKey, ECPoint publicKey = null) { PrivateKey = privateKey ?? throw new ArgumentNullException(nameof(privateKey)); PublicKey = publicKey ?? TsCrypt.RestorePublicFromPrivateKey(privateKey); }
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); }