public override byte[] ClientUdpPostDecrypt(byte[] plaindata, int datalength, out int outlength) { if (datalength <= 8) { outlength = 0; return(plaindata); } var md5 = CreateHMAC(user_key); var md5data = md5.ComputeHash(plaindata, 0, datalength - 1); if (md5data[0] != plaindata[datalength - 1]) { outlength = 0; return(plaindata); } md5 = CreateHMAC(Server.key); md5data = md5.ComputeHash(plaindata, datalength - 8, 7); var rand_len = UdpGetRandLen(random_server, md5data); outlength = datalength - rand_len - 8; encryptor = (StreamEncryptor)EncryptorFactory.GetEncryptor("chacha20", Convert.ToBase64String(user_key) + Convert.ToBase64String(md5data, 0, 16)); { var iv = new byte[8]; Array.Copy(Server.key, iv, 8); encryptor.Decrypt(iv, 8, plaindata, out _); } encryptor.Decrypt(plaindata, outlength, plaindata, out outlength); return(plaindata); }
public override byte[] ClientPostDecrypt(byte[] plaindata, int datalength, out int outlength) { var outdata = new byte[recv_buf_len + datalength]; Array.Copy(plaindata, 0, recv_buf, recv_buf_len, datalength); recv_buf_len += datalength; outlength = 0; var key = new byte[user_key.Length + 4]; user_key.CopyTo(key, 0); while (recv_buf_len > 4) { BitConverter.GetBytes(recv_id).CopyTo(key, key.Length - 4); var md5 = CreateHMAC(key); var data_len = ((recv_buf[1] ^ last_server_hash[15]) << 8) + (recv_buf[0] ^ last_server_hash[14]); var rand_len = GetRecvRandLen(data_len, random_server, last_server_hash); var len = rand_len + data_len; if (len >= 4096) { throw new ObfsException("ClientPostDecrypt data error"); } if (len + 4 > recv_buf_len) { break; } var md5data = md5.ComputeHash(recv_buf, 0, len + 2); if (md5data[0] != recv_buf[len + 2] || md5data[1] != recv_buf[len + 3] ) { throw new ObfsException("ClientPostDecrypt data uncorrect checksum"); } { var pos = 2; var outlen = data_len; Util.Utils.SetArrayMinSize2(ref outdata, outlength + outlen); var data = new byte[outlen]; Array.Copy(recv_buf, pos, data, 0, outlen); encryptor.Decrypt(data, outlen, data, out outlen); last_server_hash = md5data; if (recv_id == 1) { Server.tcp_mss = recv_tcp_mss = data[0] | (data[1] << 8); pos = 2; outlen -= 2; send_back_cmd.Add(0xff00); } else { pos = 0; } Array.Copy(data, pos, outdata, outlength, outlen); outlength += outlen; recv_buf_len -= len + 4; Array.Copy(recv_buf, len + 4, recv_buf, 0, recv_buf_len); ++recv_id; } } return(outdata); }
public void PackAuthData(byte[] data, int datalength, byte[] outdata, out int outlength) { const int authhead_len = 4 + 8 + 4 + 16 + 4; var encrypt = new byte[24]; if (Server.data is AuthDataAesChain authData) { lock (authData) { if (authData.connectionID > 0xFF000000) { authData.clientID = null; } if (authData.clientID == null) { authData.clientID = new byte[4]; g_random.GetBytes(authData.clientID); authData.connectionID = (uint)BitConverter.ToInt32(authData.clientID, 0) % 0xFFFFFD; } authData.connectionID += 1; Array.Copy(authData.clientID, 0, encrypt, 4, 4); Array.Copy(BitConverter.GetBytes(authData.connectionID), 0, encrypt, 8, 4); } } outlength = authhead_len; var encrypt_data = new byte[32]; var key = new byte[Server.Iv.Length + Server.key.Length]; Server.Iv.CopyTo(key, 0); Server.key.CopyTo(key, Server.Iv.Length); var utc_time_second = (ulong)Math.Floor(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds); var utc_time = (uint)utc_time_second; Array.Copy(BitConverter.GetBytes(utc_time), 0, encrypt, 0, 4); encrypt[12] = (byte)Server.overhead; encrypt[13] = (byte)(Server.overhead >> 8); send_tcp_mss = 1024; //random.Next(1024) + 400; recv_tcp_mss = send_tcp_mss; encrypt[14] = (byte)send_tcp_mss; encrypt[15] = (byte)(send_tcp_mss >> 8); // first 12 bytes { var rnd = new byte[4]; random.NextBytes(rnd); rnd.CopyTo(outdata, 0); var md5 = CreateHMAC(key); var md5data = md5.ComputeHash(rnd, 0, rnd.Length); last_client_hash = md5data; Array.Copy(md5data, 0, outdata, rnd.Length, 8); } // uid & 16 bytes auth data { var uid = new byte[4]; var index_of_split = Server.param.IndexOf(':'); if (index_of_split > 0) { try { var user = uint.Parse(Server.param.Substring(0, index_of_split)); user_key = System.Text.Encoding.UTF8.GetBytes(Server.param.Substring(index_of_split + 1)); BitConverter.GetBytes(user).CopyTo(uid, 0); } catch (Exception ex) { Logging.Log(LogLevel.Warn, $"Faild to parse auth param, fallback to basic mode. {ex}"); } } if (user_key == null) { random.NextBytes(uid); user_key = Server.key; } for (var i = 0; i < 4; ++i) { uid[i] ^= last_client_hash[8 + i]; } var encrypt_key = user_key; var streamEncryptor = (StreamEncryptor)EncryptorFactory.GetEncryptor("aes-128-cbc", Convert.ToBase64String(encrypt_key) + SALT); streamEncryptor.SetIV(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }); streamEncryptor.Encrypt(encrypt, 16, encrypt_data, out _); streamEncryptor.Dispose(); Array.Copy(encrypt_data, 0, encrypt, 4, 16); uid.CopyTo(encrypt, 0); } // final HMAC { var md5 = CreateHMAC(user_key); var md5data = md5.ComputeHash(encrypt, 0, 20); last_server_hash = md5data; Array.Copy(md5data, 0, encrypt, 20, 4); } encrypt.CopyTo(outdata, 12); encryptor = (StreamEncryptor)EncryptorFactory.GetEncryptor("chacha20", Convert.ToBase64String(user_key) + Convert.ToBase64String(last_client_hash, 0, 16)); { var iv = new byte[8]; Array.Copy(last_client_hash, iv, 8); encryptor.SetIV(iv); } { encryptor.Decrypt(last_server_hash, 8, outdata, out _); } // combine first chunk { var pack_outdata = new byte[outdata.Length]; PackData(data, datalength, pack_outdata, out var pack_outlength); Array.Copy(pack_outdata, 0, outdata, outlength, pack_outlength); outlength += pack_outlength; } }