예제 #1
0
파일: crypto.py 프로젝트: v3aqb/hxcrypto
 def resetPrivate(self):
     self.__key = None
     self.__ecckey = ECC(256)
     pubk_hash = ECC.b64u_to_hash(self.get_pubkey_b64u())
     _tr = QtCore.QCoreApplication.translate
     self.ui.pubkeyButton.setText(
         _tr('Crypto', 'Copy Public Key') + ' - ' + pubk_hash)
     if self.other_key:
         self.exchange(self.other_key)
예제 #2
0
 def key_xchange(self, user, user_pkey, key_len):
     # return public_key, passwd_of_user
     if hashlib.md5(user_pkey).digest() in self.pkeyuser:
         raise ValueError('public key already registered. user: %s' % user)
     if len(self.userpkeys[user]) > self._limit:
         raise ValueError('connection limit exceeded. user: %s' % user)
     ecc = ECC(key_len)
     shared_secret = ecc.get_dh_key(user_pkey)
     user_pkey_md5 = hashlib.md5(user_pkey).digest()
     self.userpkeys[user].append(user_pkey_md5)
     self.pkeyuser[user_pkey_md5] = user
     self.pkeykey[user_pkey_md5] = shared_secret
     return ecc.get_pub_key(), self.user_pass[user]
예제 #3
0
파일: server.py 프로젝트: v3aqb/hxsocks
 def key_xchange(self, user, user_pkey, key_len):
     # create_key
     if hashlib.md5(user_pkey).digest() in self.pkeyuser:
         return 0, 0
     if len(self.userpkeys[user]) > self._limit:
         self.del_key(self.userpkeys[user][0])
     ecc = ECC(key_len)
     shared_secret = ecc.get_dh_key(user_pkey)
     user_pkey_md5 = hashlib.md5(user_pkey).digest()
     self.userpkeys[user].append(user_pkey_md5)
     self.pkeyuser[user_pkey_md5] = user
     self.pkeykey[user_pkey_md5] = shared_secret
     self.pkeytime[user_pkey_md5] = time.time()
     return ecc.get_pub_key(), self.USER_PASS[user]
예제 #4
0
 def __init__(self, server_cert, limit=10):
     '''server_cert: path to server_cert'''
     self.SERVER_CERT = ECC(from_file=server_cert)
     self._limit = limit
     self.user_pass = {}
     self.userpkeys = defaultdict(deque)  # user name: client key
     self.pkeyuser = {}  # user pubkey: user name
     self.pkeykey = {}  # user pubkey: shared secret
예제 #5
0
파일: crypto.py 프로젝트: v3aqb/hxcrypto
 def exchange_edit(self):
     if self.ui.otherKeyEdit.isReadOnly():
         return
     otherkey = self.ui.otherKeyEdit.text()
     if otherkey:
         try:
             self.exchange(otherkey)
         except Exception as err:
             self.statusBar().showMessage(repr(err), 5000)
         else:
             self.other_key = otherkey
             pubk_hash = ECC.b64u_to_hash(otherkey)
             self.ui.otherKeyEdit.setText(pubk_hash)
             self.ui.otherKeyEdit.setReadOnly(True)
예제 #6
0
    async def get_key(self):
        self.logger.debug('hxsocks2 getKey')
        usn, psw = (self.proxy.username, self.proxy.password)
        self.logger.info('%s connect to server', self.name)
        from .connection import open_connection
        self.remote_reader, self.remote_writer, _ = await open_connection(
            self.proxy.hostname,
            self.proxy.port,
            proxy=self.proxy.get_via(),
            timeout=self.timeout,
            tunnel=True)

        # prep key exchange request
        self.__pskcipher = Encryptor(self._psk, self.method)
        ecc = ECC(self.__pskcipher._key_len)
        pubk = ecc.get_pub_key()
        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)

        # send key exchange request
        self.remote_writer.write(ct)
        await self.remote_writer.drain()

        # read iv
        iv = await self._rfile_read(self.__pskcipher._iv_len, self.timeout)
        self.__pskcipher.decrypt(iv)

        # read server response
        if is_aead(self.method):
            ct_len = await self._rfile_read(18, self.timeout)
            ct_len = self.__pskcipher.decrypt(ct_len)
            ct_len, = struct.unpack('!H', ct_len)
            ct = await self._rfile_read(ct_len + 16)
            ct = self.__pskcipher.decrypt(ct)
            data = ct[2:]
        else:
            resp_len = await self._rfile_read(2, self.timeout)
            resp_len = self.__pskcipher.decrypt(resp_len)
            resp_len, = struct.unpack('>H', resp_len)
            data = await self._rfile_read(resp_len)
            data = self.__pskcipher.decrypt(data)

        data = io.BytesIO(data)

        resp_code = byte2int(data.read(1))
        if resp_code == 0:
            self.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.
            host, port = self.proxy._host_port
            server_id = '%s_%d' % (host, port)
            if server_id not in KNOWN_HOSTS:
                self.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:
                self.logger.error('hxs: server %s certificate mismatch! PLEASE CHECK!', server_id)
                raise ConnectionResetError(0, 'hxs: bad certificate')

            if auth == hmac.new(psw.encode(), pubk + server_key + usn.encode(), hashlib.sha256).digest():
                try:
                    ECC.verify_with_pub_key(server_cert, auth, signature, self.hash_algo)
                    shared_secret = ecc.get_dh_key(server_key)
                    self.logger.debug('hxs key exchange success')
                    self.__cipher = AEncryptor(shared_secret, self.method, CTX)
                    # start reading from connection
                    asyncio.ensure_future(self.read_from_connection())
                    asyncio.ensure_future(self.stat())
                    self.connected = True
                    return
                except InvalidSignature:
                    self.logger.error('hxs getKey Error: server auth failed, bad signature')
            else:
                self.logger.error('hxs getKey Error: server auth failed, bad username or password')
        else:
            self.logger.error('hxs getKey Error. bad password or timestamp.')
        raise ConnectionResetError(0, 'hxs getKey Error')
예제 #7
0
파일: crypto.py 프로젝트: v3aqb/hxcrypto
class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_Crypto()
        self.ui.setupUi(self)

        self.__ecckey = None

        self.__key = None
        self.other_key = None
        self._last_active = time.time()

        self.ui.textEdit.setWordWrapMode(3)
        self.ui.psktextEdit.setWordWrapMode(3)

        self.ui.pubkeyButton.clicked.connect(self.copy_pubkey)
        self.ui.otherKeyEdit.editingFinished.connect(self.exchange_edit)

        self.ui.encryptButton.clicked.connect(self.encrypt)
        self.ui.decryptButton.clicked.connect(self.decrypt)
        self.ui.resetPrivateButton.clicked.connect(self.resetPrivate)
        self.ui.resetExchangeButton.clicked.connect(self.resetExchange)
        self.ui.decryptButton.clicked.connect(self.decrypt)

        self.ui.PSKencryptButton.clicked.connect(self.pskencrypt)
        self.ui.PSKdecryptButton.clicked.connect(self.pskdecrypt)

        self.ui.b64EncodeButton.clicked.connect(self.b64encode)
        self.ui.b64DecodeButton.clicked.connect(self.b64decode)

        self.resetPrivate()
        self.show()

    def resetPrivate(self):
        self.__key = None
        self.__ecckey = ECC(256)
        pubk_hash = ECC.b64u_to_hash(self.get_pubkey_b64u())
        _tr = QtCore.QCoreApplication.translate
        self.ui.pubkeyButton.setText(
            _tr('Crypto', 'Copy Public Key') + ' - ' + pubk_hash)
        if self.other_key:
            self.exchange(self.other_key)

    def get_pubkey_b64u(self):
        return self.__ecckey.get_pub_key_b64u()

    def copy_pubkey(self):
        public_key = self.get_pubkey_b64u()
        app = QtWidgets.QApplication.instance()
        cb = app.clipboard()
        cb.setText(public_key)

    def resetExchange(self):
        self.__key = None
        self.other_key = None
        self.ui.otherKeyEdit.setText("")
        self.ui.otherKeyEdit.setReadOnly(False)

    def exchange(self, otherkey):
        self.__key = self.__ecckey.get_dh_key_b64u(otherkey)

    def exchange_edit(self):
        if self.ui.otherKeyEdit.isReadOnly():
            return
        otherkey = self.ui.otherKeyEdit.text()
        if otherkey:
            try:
                self.exchange(otherkey)
            except Exception as err:
                self.statusBar().showMessage(repr(err), 5000)
            else:
                self.other_key = otherkey
                pubk_hash = ECC.b64u_to_hash(otherkey)
                self.ui.otherKeyEdit.setText(pubk_hash)
                self.ui.otherKeyEdit.setReadOnly(True)

    def encrypt(self):
        if time.time() - self._last_active < 0.3:
            return

        if not self.__key:
            self.statusBar().showMessage("key exchange not finished", 5000)
            return

        plain_text = self.ui.textEdit.toPlainText()
        if not plain_text:
            return
        try:
            cipher_text = encrypt(self.__key, plain_text)
        except Exception as err:
            self.statusBar().showMessage(repr(err), 5000)
            return

        self.ui.textEdit.setPlainText(cipher_text)

        self._last_active = time.time()

    def decrypt(self):
        if time.time() - self._last_active < 0.3:
            return

        if not self.__key:
            self.statusBar().showMessage("key exchange not finished", 5000)
            return

        cipher_text = self.ui.textEdit.toPlainText()
        if not cipher_text:
            return

        try:
            plain_text = decrypt(self.__key, cipher_text)
            if not plain_text:
                return
            self.ui.textEdit.setPlainText(plain_text)
        except Exception as err:
            self.statusBar().showMessage(repr(err), 5000)
            return

        self._last_active = time.time()

    def pskencrypt(self):
        if time.time() - self._last_active < 0.3:
            return

        plain_text = self.ui.psktextEdit.toPlainText()
        if not plain_text:
            return

        key = self.ui.pskEdit.text()
        key = key_to_bytes(key)

        try:
            cipher_text = encrypt(key, plain_text)
            if not cipher_text:
                return
        except Exception as err:
            self.statusBar().showMessage(repr(err), 5000)
            return

        self.ui.psktextEdit.setPlainText(cipher_text)

        self._last_active = time.time()

    def pskdecrypt(self):
        if time.time() - self._last_active < 0.3:
            return

        cipher_text = self.ui.psktextEdit.toPlainText()
        if not cipher_text:
            return

        key = self.ui.pskEdit.text()
        key = key_to_bytes(key)

        try:
            plain_text = decrypt(key, cipher_text)
            if not plain_text:
                return
            self.ui.psktextEdit.setPlainText(plain_text)
        except Exception as err:
            self.statusBar().showMessage(repr(err), 5000)
            return

        self._last_active = time.time()

    def b64decode(self):
        text = self.ui.b64TextEdit.toPlainText()
        text_bytes = text.encode('utf-8')
        try:
            result = base64.urlsafe_b64decode(text_bytes).decode()
            self.ui.b64TextEdit.setPlainText(result)
        except Exception as err:
            self.statusBar().showMessage(repr(err), 5000)
            return

    def b64encode(self):
        text = self.ui.b64TextEdit.toPlainText()
        text_bytes = text.encode('utf-8')
        try:
            result = base64.urlsafe_b64encode(text_bytes).decode()
            self.ui.b64TextEdit.setPlainText(result)
        except Exception as err:
            self.statusBar().showMessage(repr(err), 5000)
            return