I'm trying to use TCP sockets to send an encrypted message from one computer to another. The server encrypts the string, sends it to the client, and the client decrypts the string and prints the raw version. However, I keep getting this error on the client:
ValueError: IV must be 16 bytes long
The server code is:
import socket, hashlib, base64
from Crypto.Cipher import AES
from Crypto import Random
BLOCK_SIZE = 16
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
password = "sdfsdfJDFJDSF8sd9fs"
def encrypt(raw, password):
private_key = hashlib.sha256(password.encode("utf-8")).digest()
raw = pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(private_key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(raw))
def decrypt(enc, password):
private_key = hashlib.sha256(password.encode("utf-8")).digest()
enc = base64.b64decode(enc)
iv = enc[:16]
cipher = AES.new(private_key, AES.MODE_CBC, iv)
return unpad(cipher.decrypt(enc[16:]))
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("192.168.1.150", 443))
s.listen(5)
print("\n\nListening...\n\n")
conn, addr = s.accept()
print("\n\nConnection from\n\n")
message="hello world"
data=encrypt(message, password)
s.send(data)
The client code is:
import socket, base64, hashlib
from Crypto.Cipher import AES
from Crypto import Random
BLOCK_SIZE = 16
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
password = "sdfsdfJDFJDSF8sd9fs"
def encrypt(raw, password):
private_key = hashlib.sha256(password.encode("utf-8")).digest()
raw = pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(private_key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(raw))
def decrypt(enc, password):
private_key = hashlib.sha256(password.encode("utf-8")).digest()
enc = base64.b64decode(enc)
iv = enc[:16]
cipher = AES.new(private_key, AES.MODE_CBC, iv)
return unpad(cipher.decrypt(enc[16:]))
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.1.150", 443))
data=s.recv(1024)
shellcode_raw=decrypt(data, password)
print(shellcode_raw)
I figured it out. I believe it was an error in the conversion of bytes to string, but I'm not sure. I also increased the number of bytes in the s.recv(1024)
function to s.recv(4096)
Here is the code.
The server code:
import base64
import hashlib
import socket
from Crypto import Random
from Crypto.Cipher import AES
class AESCipher(object):
def __init__(self, key):
self.bs = AES.block_size
self.key = hashlib.sha256(key.encode()).digest()
def encrypt(self, raw):
raw = self._pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(raw.encode()))
def decrypt(self, enc):
enc = base64.b64decode(enc)
iv = enc[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s)-1:])]
string="super secure"
password="djknBDS89dHFS(*HFSD())"
enc_string=str(AESCipher(password).encrypt(string))
enc_string_2=AESCipher(password).encrypt(string)
dec_string=str(AESCipher(password).decrypt(enc_string_2))
print("This is the password " + password)
print("Decrypted string: " + string)
print("Encrypted string: " + enc_string)
print("Decrypted string (v2): " + str(dec_string))
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('192.168.1.150', 4444))
sock.listen(5)
print("Listening for connections...")
conn, addr = sock.accept()
conn.send(enc_string_2)
conn.close()
The client code:
import socket
import base64
from Crypto import Random
from Crypto.Cipher import AES
import hashlib
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('192.168.1.150', 4444))
class AESCipher(object):
def __init__(self, key):
self.bs = AES.block_size
self.key = hashlib.sha256(key.encode()).digest()
def encrypt(self, raw):
raw = self._pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(raw.encode()))
def decrypt(self, enc):
enc = base64.b64decode(enc)
iv = enc[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s)-1:])]
password="djknBDS89dHFS(*HFSD())"
data=sock.recv(4096)
decoded=AESCipher(password).decrypt(data.decode('utf-8'))
print(str(decoded))
sock.close()