diff --git a/shadowsocks/obfsplugin/auth_akarin.py b/shadowsocks/obfsplugin/auth_akarin.py index 903d5f1..fd6cbe5 100644 --- a/shadowsocks/obfsplugin/auth_akarin.py +++ b/shadowsocks/obfsplugin/auth_akarin.py @@ -297,7 +297,7 @@ class auth_akarin_rand(auth_base): v = self.trapezoid_random_float(d) return int(v * max_val) - def send_rnd_data_len(self, buf_size: int, last_hash, random: xorshift128plus) -> int: + def send_rnd_data_len(self, buf_size: int, last_hash: bytes, random: xorshift128plus) -> int: if buf_size + self.server_info.overhead > self.send_tcp_mss: random.init_from_bin_len(last_hash, buf_size) return random.next() % 521 @@ -331,7 +331,7 @@ class auth_akarin_rand(auth_base): random.init_from_bin(last_hash) return random.next() % 127 - def rnd_data(self, buf_size: int, buf: bytes, last_hash, random: xorshift128plus) -> bytes: + def rnd_data(self, buf_size: int, buf: bytes, last_hash: bytes, random: xorshift128plus) -> bytes: rand_len = self.send_rnd_data_len(buf_size, last_hash, random) rnd_data_buf = rand_bytes(rand_len) @@ -345,6 +345,31 @@ class auth_akarin_rand(auth_base): return buf def pack_client_data(self, buf: bytes) -> bytes: + """ + + pack_data with_cmd= + |ushort(0xff00^ushort(last_client_hash[14:16]))| + |ushort(len(origin data)^ushort(last_client_hash[12:14]))|encrypt(origin data)| + + pack_data without_cmd= + |ushort(len(origin data)^ushort(last_client_hash[14:16]))|encrypt(origin data)| + + HMAC_key= + |user_key|uint(last_pack_id)| + + next_client_hash= + HMAC_sign(key:(HMAC_key), be sign data:(pack_data)) + + next_pack_id= + uint((pack_id + 1)&0xFFFFFFFF) + + pack_out= + |(pack_data)|next_client_hash| + + + :param buf: bytes origin data + :return: bytes packed data + """ buf = self.encryptor.encrypt(buf) if self.send_back_cmd: cmd_len = 2 @@ -359,12 +384,33 @@ class auth_akarin_rand(auth_base): length = len(buf) ^ struct.unpack(' bytes: + """ + + pack_data= + |ushort(len(origin data)^ushort(last_client_hash[14:16]))|encrypt(origin data)| + + HMAC_key= + |user_key|uint(last_pack_id)| + + next_client_hash= + HMAC_sign(key:(HMAC_key), be sign data:(pack_data)) + + next_pack_id= + uint((pack_id + 1)&0xFFFFFFFF) + + pack_out= + |(pack_data)|next_client_hash| + + + :param buf: bytes origin data + :return: bytes packed data + """ buf = self.encryptor.encrypt(buf) data = self.rnd_data(len(buf), buf, self.last_server_hash, self.random_server) mac_key = self.user_key + struct.pack(' bytes: + """ + ### construct the client first&auth pack + + plain_auth_data= + |auth_data|ushort(server_info.overhead)|ushort(tcp_mss)| + + check_head 1st_pair= + |rand_bytes(4)| + + mac_key= + |server_info.iv|server_info.key| + + client_hash= + |HMAC_sign(mac_key, data:(check_head 1st_pair))| + + check_head 2ed_pair= + |client_hash[:8]| + + check_head= + |(check_head 1st_pair)|(check_head 2ed_pair)| + + user_origin_id= + |(uid in protocol_param)| or |rand_bytes(4)| + + user_encoded_id= + |uint_bytes(uint_number(uid)^uint_number(client_hash[8:12]))| + {== equal as ==|uint_bytes(uid)^client_hash[8:12]|} + + encryptor_1_key= + |bytes(base64(user_key))|protocol_salt| + + encrypted_auth_data= + |user_encoded_id| + |encryptor( + key:(encryptor_1_key), + data:(plain_auth_data), + mode:('aes-128-cbc'), + encipher_vi:(b'\x00' * 16) + )[16:]| + + server_hash= + |HMAC_sign(user_key, encrypted_auth_data)| + + pack_out= + |check_head|encrypted_auth_data|server_hash[:4]|pack_client_data(buf)| + + connect_encryptor_key= + |bytes(base64(user_key))|bytes(base64(client_hash[0:16]))| + + connect_encryptor_encipher_vi= + |client_hash[:8]| + + connect_encryptor_decipher_vi= + |server_hash[:8]| + + connect_encryptor= + |encryptor( + key:(connect_encryptor_key), + data:(plain_auth_data), + mode:('chacha20'), + encipher_vi:(connect_encryptor_encipher_vi), + decipher_vi:(connect_encryptor_decipher_vi) + )| + + :param auth_data: + :param buf: + :return: + """ data = auth_data + # TODO FIX THIS this need be a little ending encode ushort , + # TODO it need same as decoder on `server_post_decrypt()` for recv_tcp_mss + # a random size tcp max size for mss exchange when c->s self.send_tcp_mss = struct.unpack('>H', rand_bytes(2))[0] % 1024 + 400 data = data + (struct.pack(' bytes: + """ + + auth_data= + |uint(utc_time)|connection_id:(rand_bytes(4))|uint(connection_id)| + + :return: bytes auth data + """ + utc_time: int = int(time.time()) & 0xFFFFFFFF if self.server_info.data.connection_id > 0xFF000000: self.server_info.data.local_client_id = b'' if not self.server_info.data.local_client_id: