客户端-服务器python将字节转换为字符串

时间:2018-10-12 21:41:38

标签: python cryptography type-conversion byte python-unicode

我在python中创建了一个客户端-服务器模型。 这就像一个聊天室,但是我尝试使用来自cryptography.io的“ CTR”对消息进行加密。 当我在客户端中进行加密和解密时,它工作得很好,但是当我将其发送到服务器时,总是显示以下内容:

>     > Task exception was never retrieved
>     future: <Task finished coro=<handle_echo() done, defined at Server.py:43> exception=UnicodeDecodeError('utf-8', b'\x8f.\xcb', 0,
> 1, 'invalid start byte')>
>     Traceback (most recent call last):
>       File "Server.py", line 53, in handle_echo
>         data = srvwrk.process(data)
>       File "Server.py", line 25, in process
>         txt = msg.decode()
>     UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8f in position 0: invalid start byte

对不起,我的英语,谢谢

客户端:

# Código baseado em https://docs.python.org/3.6/library/asyncio-stream.html#tcp-echo-client-using-streams
import asyncio
import socket
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend


conn_port = 8888
max_msg_size = 9999

class Client:
    """ Classe que implementa a funcionalidade de um CLIENTE. """
    def __init__(self, sckt=None):
        """ Construtor da classe. """
        self.sckt = sckt
        self.msg_cnt = 0
        def process(self, msg=b""):
            """ Processa uma mensagem (`bytestring`) enviada pelo SERVIDOR.
            Retorna a mensagem a transmitir como resposta (`None` para
            finalizar ligação) """
            self.msg_cnt +=1


            backend = default_backend()
            key = os.urandom(32)
            iv = os.urandom(16)
            cipher = Cipher(algorithms.AES(key), modes.CTR(iv), backend=backend)


            print('Received (%d): %r' % (self.msg_cnt , msg.decode()))
            print('Input message to send (empty to finish)')
            new_msg = input().encode()
            encryptor = cipher.encryptor()
            ct = encryptor.update(new_msg) + encryptor.finalize()

            print(ct)
            return ct if len(ct)>0 else None

            #
            #
            # Funcionalidade Cliente/Servidor
            #
            # obs: não deverá ser necessário alterar o que se segue
            #


            @asyncio.coroutine
            def tcp_echo_client(loop=None):
                if loop is None:
                    loop = asyncio.get_event_loop()

                    reader, writer = yield from asyncio.open_connection('127.0.0.1',
                    conn_port, loop=loop)
                    addr = writer.get_extra_info('peername')
                    client = Client(addr)
                    msg = client.process()
                    while msg:
                        writer.write(msg)
                        msg = yield from reader.read(max_msg_size)
                        if msg :
                            msg = client.process(msg)
                        else:
                            break
                            writer.write(b'\n')
                            print('Socket closed!')
                            writer.close()

                            def run_client():
                                loop = asyncio.get_event_loop()
                                loop.run_until_complete(tcp_echo_client())


                                run_client()

这是服务器: 我试图将'utf-8'放入txt = msg.decode()...,但始终显示相同的错误

# Código baseado em https://docs.python.org/3.6/library/asyncio-stream.html#tcp-echo-client-using-streams
import asyncio
import codecs
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend

conn_cnt = 0
conn_port = 8888
max_msg_size = 9999

class ServerWorker(object):
    """ Classe que implementa a funcionalidade do SERVIDOR. """
    def __init__(self, cnt, addr=None):
        """ Construtor da classe. """
        self.id = cnt
        self.addr = addr
        self.msg_cnt = 0
        def process(self, msg):
            """ Processa uma mensagem (`bytestring`) enviada pelo CLIENTE.
            Retorna a mensagem a transmitir como resposta (`None` para
            finalizar ligação) """
            self.msg_cnt += 1

            txt = msg.decode()
            print(txt)
            decryptor = cipher.decryptor()
            ctt = decryptor.update(msg) + decryptor.finalize()
            print(ctt)
            print('%d : %r' % (self.id,txt))
            new_msg = txt.upper().encode()
            return new_msg if len(new_msg)>0 else None


            #
            #
            # Funcionalidade Cliente/Servidor
            #
            # obs: não deverá ser necessário alterar o que se segue
            #


            @asyncio.coroutine
            def handle_echo(reader, writer):
                global conn_cnt
                conn_cnt +=1
                addr = writer.get_extra_info('peername')
                srvwrk = ServerWorker(conn_cnt, addr)
                data = yield from reader.read(max_msg_size)
                while True:
                    if not data: continue
                    if data[:1]==b'\n': break
                    data = srvwrk.process(data)
                    if not data: break
                    writer.write(data)
                    yield from writer.drain()
                    data = yield from reader.read(max_msg_size)
                    print("[%d]" % srvwrk.id)
                    writer.close()


                    def run_server():
                        loop = asyncio.get_event_loop()
                        coro = asyncio.start_server(handle_echo, '127.0.0.1', conn_port, loop=loop)
                        server = loop.run_until_complete(coro)
                        # Serve requests until Ctrl+C is pressed
                        print('Serving on {}'.format(server.sockets[0].getsockname()))
                        print('  (type ^C to finish)\n')
                        try:
                            loop.run_forever()
                        except KeyboardInterrupt:
                            pass
                            # Close the server
                            server.close()
                            loop.run_until_complete(server.wait_closed())
                            loop.close()
                            print('\nFINISHED!')

                            run_server()

1 个答案:

答案 0 :(得分:0)

您似乎先对消息进行编码然后对其进行加密,但是尝试对消息进行解码然后对其进行解密。如果先解密邮件然后再解码,则应该可以解决问题。

我认为将解密代码更改为此应该可以解决问题:

decryptor = cipher.decryptor()
ctt = decryptor.update(msg) + decryptor.finalize()
print(ctt)
txt = cct.decode()
print(txt)