def getKey(self): with newkey_lock[self.serverid]: if self.serverid not in keys: for _ in range(2): logger.debug('hxsocks getKey') host, port, usn, psw = (self.hxsServer.hostname, self.hxsServer.port, self.hxsServer.username, self.hxsServer.password) if self._sock is None: logger.debug('hxsocks connect') from connection import create_connection self._sock = create_connection((host, port), self.timeout, parentproxy=self.parentproxy, tunnel=True) self.pskcipher = encrypt.Encryptor(self.PSK, self.method) acipher = ECC(self.pskcipher.key_len) pubk = acipher.get_pub_key() logger.debug('hxsocks send key exchange request') ts = struct.pack('>I', int(time.time())) padding_len = random.randint(64, 255) data = chr(10) + ts + chr(len(pubk)) + pubk + hmac.new(psw.encode(), ts + pubk + usn.encode(), hashlib.sha256).digest()\ + chr(padding_len) + b'\x00' * padding_len self._sock.sendall(self.pskcipher.encrypt(data)) fp = self._sock.makefile('rb', 0) resp_len = 1 if self.pskcipher.decipher else self.pskcipher.iv_len + 1 resp = ord(self.pskcipher.decrypt(fp.read(resp_len))) if resp == 0: logger.debug('hxsocks read key exchange respond') pklen = ord(self.pskcipher.decrypt(fp.read(1))) server_key = self.pskcipher.decrypt(fp.read(pklen)) auth = self.pskcipher.decrypt(fp.read(32)) pklen = ord(self.pskcipher.decrypt(fp.read(1))) server_cert = self.pskcipher.decrypt(fp.read(pklen)) sig_len = ord(self.pskcipher.decrypt(fp.read(1))) signature = self.pskcipher.decrypt(fp.read(sig_len)) pad_len = ord(self.pskcipher.decrypt(fp.read(1))) self.pskcipher.decrypt(fp.read(pad_len)) # TODO: ask user if a certificate should be accepted or not. if host not in known_hosts: logger.info('hxs: server %s new cert %s saved.' % (host, hashlib.sha256(server_cert).hexdigest()[:8])) with open('./.hxs_known_hosts/' + host + '.cert', 'wb') as f: f.write(server_cert) known_hosts[host] = server_cert elif known_hosts[host] != server_cert: logger.error('hxs: server %s certificate mismatch! PLEASE CHECK!' % host) raise OSError(0, 'hxs: bad certificate') if auth == hmac.new(psw.encode(), pubk + server_key + usn.encode(), hashlib.sha256).digest(): if ECC.verify_with_pub_key(server_cert, auth, signature, self.hash_algo): shared_secret = acipher.get_dh_key(server_key) keys[self.serverid] = (hashlib.md5(pubk).digest(), shared_secret) self.cipher = encrypt.AEncryptor(keys[self.serverid][1], self.method, SALT, CTX, 0) logger.debug('hxs key exchange success') return else: logger.error('hxs getKey Error: server auth failed, bad signature') else: logger.error('hxs getKey Error: server auth failed, bad username or password') else: fp.read(ord(self.pskcipher.decrypt(fp.read(1)))) logger.error('hxs getKey Error. bad password or timestamp.') else: raise IOError(0, 'hxs getKey Error') else: self.cipher = encrypt.AEncryptor(keys[self.serverid][1], self.method, SALT, CTX, 0)
def getKey(self): with newkey_lock[self.serverid]: if self.serverid not in keys: for _ in range(2): logger.debug('hxsocks getKey') host, port, usn, psw = (self.hxsServer.hostname, self.hxsServer.port, self.hxsServer.username, self.hxsServer.password) if self._sock is None: logger.debug('hxsocks connect') from connection import create_connection self._sock = create_connection( (host, port), self.timeout, parentproxy=self.parentproxy, tunnel=True) self.pskcipher = encrypt.Encryptor( self.PSK, self.method) self._rfile = self._sock.makefile('rb') self._header_sent = False self._header_received = False acipher = ECC(self.pskcipher.key_len) pubk = acipher.get_pub_key() logger.debug('hxsocks send key exchange request') ts = struct.pack('>I', int(time.time())) padding_len = random.randint(64, 255) data = b''.join([ ts, chr(len(pubk)).encode('latin1'), pubk, hmac.new(psw.encode(), ts + pubk + usn.encode(), hashlib.sha256).digest(), b'\x00' * padding_len ]) data = chr(10).encode() + struct.pack('>H', len(data)) + data self._sock_sendall(self.pskcipher.encrypt(data)) resp_len = 2 if self.pskcipher.decipher else self.pskcipher.iv_len + 2 resp_len = self.pskcipher.decrypt( self._rfile_read(resp_len)) resp_len = struct.unpack('>H', resp_len)[0] data = self.pskcipher.decrypt(self._rfile_read(resp_len)) data = io.BytesIO(data) resp_code = byte2int(data.read(1)) if resp_code == 0: logger.debug('hxsocks read key exchange respond') pklen = byte2int(data.read(1)) scertlen = byte2int(data.read(1)) siglen = byte2int(data.read(1)) server_key = data.read(pklen) auth = data.read(32) server_cert = data.read(scertlen) signature = data.read(siglen) # TODO: ask user if a certificate should be accepted or not. if host not in known_hosts: logger.info( 'hxs: server %s new cert %s saved.' % (host, hashlib.sha256(server_cert).hexdigest()[:8])) with open('./.hxs_known_hosts/' + host + '.cert', 'wb') as f: f.write(server_cert) known_hosts[host] = server_cert elif known_hosts[host] != server_cert: logger.error( 'hxs: server %s certificate mismatch! PLEASE CHECK!' % host) raise OSError(0, 'hxs: bad certificate') if auth == hmac.new(psw.encode(), pubk + server_key + usn.encode(), hashlib.sha256).digest(): if ECC.verify_with_pub_key(server_cert, auth, signature, self.hash_algo): shared_secret = acipher.get_dh_key(server_key) keys[self.serverid] = ( hashlib.md5(pubk).digest(), shared_secret) self.cipher = encrypt.AEncryptor( keys[self.serverid][1], self.method, SALT, CTX, 0, MAC_LEN) logger.debug('hxs key exchange success') return else: logger.error( 'hxs getKey Error: server auth failed, bad signature' ) else: logger.error( 'hxs getKey Error: server auth failed, bad username or password' ) else: logger.error( 'hxs getKey Error. bad password or timestamp.') else: raise IOError(0, 'hxs getKey Error') else: self.cipher = encrypt.AEncryptor(keys[self.serverid][1], self.method, SALT, CTX, 0, MAC_LEN)
def getKey(self): logger.debug('hxsocks2 getKey') host, port, usn, psw = (self.hxsServer.hostname, self.hxsServer.port, self.hxsServer.username, self.hxsServer.password) logger.debug('hxsocks2 connect to server') from connection import create_connection self._sock = create_connection((host, port), self.timeout, parentproxy=self.parentproxy, tunnel=True) self._rfile = self._sock.makefile('rb') acipher = ECC(self.__pskcipher._key_len) pubk = acipher.get_pub_key() logger.debug('hxsocks2 send key exchange request') ts = int(time.time()) // 30 ts = struct.pack('>I', ts) padding_len = random.randint(64, 255) data = b''.join([chr(len(pubk)).encode('latin1'), pubk, hmac.new(psw.encode(), ts + pubk + usn.encode(), hashlib.sha256).digest(), b'\x00' * padding_len]) data = chr(20).encode() + struct.pack('>H', len(data)) + data ct = self.__pskcipher.encrypt(data) self._sock.sendall(ct) self.__pskcipher.decrypt(self._rfile.read(self.__pskcipher._iv_len)) if encrypt.is_aead(self.method): ct_len = self.__pskcipher.decrypt(self._rfile.read(18)) ct_len, = struct.unpack('!H', ct_len) ct = self.__pskcipher.decrypt(self._rfile.read(ct_len + 16)) data = ct[2:] else: resp_len = self.__pskcipher.decrypt(self._rfile.read(2)) resp_len, = struct.unpack('>H', resp_len) data = self.__pskcipher.decrypt(self._rfile.read(resp_len)) data = io.BytesIO(data) resp_code = byte2int(data.read(1)) if resp_code == 0: logger.debug('hxsocks read key exchange respond') pklen = byte2int(data.read(1)) scertlen = byte2int(data.read(1)) siglen = byte2int(data.read(1)) server_key = data.read(pklen) auth = data.read(32) server_cert = data.read(scertlen) signature = data.read(siglen) # TODO: ask user if a certificate should be accepted or not. server_id = '%s_%d' % (host, port) if server_id not in known_hosts: logger.info('hxs: server %s new cert %s saved.' % (server_id, hashlib.sha256(server_cert).hexdigest()[:8])) with open('./.hxs_known_hosts/' + server_id + '.cert', 'wb') as f: f.write(server_cert) known_hosts[server_id] = server_cert elif known_hosts[server_id] != server_cert: logger.error('hxs: server %s certificate mismatch! PLEASE CHECK!' % server_id) raise OSError(0, 'hxs: bad certificate') if auth == hmac.new(psw.encode(), pubk + server_key + usn.encode(), hashlib.sha256).digest(): if ECC.verify_with_pub_key(server_cert, auth, signature, self.hash_algo): shared_secret = acipher.get_dh_key(server_key) logger.debug('hxs key exchange success') self.__cipher = AEncryptor(shared_secret, self.method, CTX) return else: logger.error('hxs getKey Error: server auth failed, bad signature') else: logger.error('hxs getKey Error: server auth failed, bad username or password') else: logger.error('hxs getKey Error. bad password or timestamp.') raise OSError(0, 'hxs getKey Error')