Search code examples
python-2.7socketsencryptionaes

Sending Encrypted Data Through Socket And Decrypting Doesn't Work


I am creating a simple encryption software. The problem I currently have is that sending encrypted aes file data through a socket doesn't work. At the receiving end, the file that should be written to is empty. I have looked through my code for a good while and can't see to solve it.

I have made a version without networking. I have been able to send a small file up to 8 KB on a different version

My Program Is Function Based So The Program Branches Off From The Main Menu To Other Menues And Functions. Since There is A Bit Of Jumping, It Would Be Best To Show All The Code. https://github.com/BaconBombz/Dencryptor/blob/Version-2.0/Dencryptor.py

The socket connects, and all required data is sent. Then, the file is AES encrypted and sent through the socket. The Receiving end writes encrypted data to a file and decrypts it. The program will say the file was sent but on the recieving end, the program spits out a struct error because the file that should have the encrypted data is empty.


Solution

  • The code is too non-minimal so here's a minimal example of downloading an unencrypted file. Also, TCP is a streaming protocol and using sleeps to separate your data is incorrect. Define a protocol for the byte stream instead. This is the protocol of my example:

    1. Open the connection.
    2. Send the UTF-8-encoded filename followed by a newline.
    3. Send the encoded file size in decimal followed by a newline.
    4. Send the file bytes.
    5. Close the connection.

    Note this is Python 3 code since Python 2 is obsolete and support has ended.

    server.py

    from socket import *
    import os
    
    CHUNKSIZE = 1_000_000
    
    # Make a directory for the received files.
    os.makedirs('Downloads',exist_ok=True)
    
    sock = socket()
    sock.bind(('',5000))
    sock.listen(1)
    
    with sock:
        while True:
            client,addr = sock.accept()
    
            # Use a socket.makefile() object to treat the socket as a file.
            # Then, readline() can be used to read the newline-terminated metadata.
            with client, client.makefile('rb') as clientfile:
                filename = clientfile.readline().strip().decode()
                length = int(clientfile.readline())
                print(f'Downloading {filename}:{length}...')
                path = os.path.join('Downloads',filename)
    
                # Read the data in chunks so it can handle large files.
                with open(path,'wb') as f:
                    while length:
                        chunk = min(length,CHUNKSIZE)
                        data = clientfile.read(chunk)
                        if not data: break # socket closed
                        f.write(data)
                        length -= len(data)
    
                if length != 0:
                    print('Invalid download.')
                else:
                    print('Done.')
    

    client.py

    from socket import *
    import os
    
    CHUNKSIZE = 1_000_000
    
    filename = input('File to upload: ')
    
    sock = socket()
    sock.connect(('localhost',5000))
    with sock,open(filename,'rb') as f:
        sock.sendall(filename.encode() + b'\n')
        sock.sendall(f'{os.path.getsize(filename)}'.encode() + b'\n')
    
        # Send the file in chunks so large files can be handled.
        while True:
            data = f.read(CHUNKSIZE)
            if not data: break
            sock.sendall(data)