Error 65537 while instatiating the CBC mode - python

I have been using the PyCryptoDome library to encrypt some communications between a client and a server. Here is how the protocol goes.
The server sends an RSA public key to the client.
The client generates an AES key
The client encrypts it. encrypts it using the public key (with the PKCS1_OAEP encrypt function)
The encrypted key is sent to the server.
The server decrypts the key
The server and client switch to AES-CBC to encrypt communications.
After that, when the client sends a message, the server decrypts it, uses it for what needs to be done with it, and then sends it back. All goes well until the client tries to decrypt the message that is sent back by the server. The thread for receiving messages stops, due to:
Error 65537 while instatiating the CBC mode
Different error codes happen when using different AES modes.
Here is my modified AESCipher Class:
import binascii
from Crypto import Random
from Crypto.Cipher import AES
class AESCipher(object):
def __init__(self, key):
self.key = key
self.pad = lambda s: s + (AES.block_size - len(s) % AES.block_size) * \
chr(AES.block_size - len(s) % AES.block_size)
self.unpad = lambda s: s[:-ord(s[len(s) - 1:])]
def encrypt(self, raw):
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return binascii.b2a_hex(iv + cipher.encrypt(self.pad(raw)))
def decrypt(self, enc):
enc = binascii.a2b_hex(enc)
iv = enc[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return self.unpad(cipher.decrypt(enc[AES.block_size:]))
Client receiving side (the error-causing side):
def recvMesgThread(netcat, output, aescipher):
while True:
try:
data = netcat.recv_until('\r\n').replace('\r\n', '')
except NetcatError:
print('Lost connection to server!')
sys.exit(0)
if data[:5] == '/MESG' and data[-5:] =='MESG/' :
try:
output.append(aescipher.decrypt(buf[5:-5]))
except Exception as e:
print(e)

Well, this is embarrassing...
The problem was a typo. Line 11 tries to decrypt the buf variable, which doesn't exist. The data variable was the one that contained what I needed.

Related

Python3: UnicodeDecodeError: 'utf-8' codec can't decode byte 0x83 in position 1: invalid start byte

I am dealing with MQTT communication again.
I am writting a python program which implement this communication.
In the publisher script, I am encrypting a message (using AES encryption) and sending it to the subscriber who will decrypt that message.
When I run the program, Iam getting that error in the subscriber part:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x83 in position 1: invalid start byte
I've searched for the solution but without any result !
This is the publisher script which works fine
import paho.mqtt.client as mqtt
import time
from os import urandom
from Crypto.Cipher import AES
port = 1883
brocker = "localhost"
message = "MessageToEncrypt"
topic = "Auth"
secret_key = urandom(16)
iv = urandom(16)
obj = AES.new(secret_key, AES.MODE_CBC, iv)
encrypted_text = obj.encrypt(message)
def on_publish(client,userdata,mid):
#the mid value is the message ID
print("on_publish callback mid: "+str(mid))
print("The message published is: " + message)
print("Encrypted msg: "+str(encrypted_text))
print(type(encrypted_text))
def on_connect(client, userdata, flags, rc):
print("Client connected with this connection code: "+str(rc))
def on_disconnect(client,userdata,rc):
print("client disconnected \n")
def main():
try:
clt = mqtt.Client("client1")
print("Client created successfully \n")
clt.on_connect = on_connect
clt.on_publish = on_publish
clt.connect(brocker,port)
print("Client connected \n")
ret = clt.publish(topic,encrypted_text)
time.sleep(4)
print("The publish result is : "+str(ret)+"\n")
clt.on_disconnect = on_disconnect
clt.disconnect()
except Exception as inst:
print("\n Exception found \n")
print(type(inst))
print(inst.args)
print(inst)
print("\n")
main()
and this is the subscriber script:
import paho.mqtt.client as mqtt
import time
from os import urandom
from Crypto.Cipher import AES
port = 1883
brocker = "localhost"
topic = "Auth"
secret_key = urandom(16)
iv = urandom(16)
rev_obj = AES.new(secret_key, AES.MODE_CBC, iv)
def on_connect(client, userdata, flags, rc):
print("Client connected with this connection code: " +str(rc))
def on_message(client, userdata, message):
#print("on_message function")
time.sleep(1)
msg_received = message.payload
print(type(msg_received))
print("the encrypred message rceived is :")
print(msg_received)
decrypted_text = rev_obj.decrypt(msg_received)
print("The decrypted text", decrypted_text.decode('utf-8'))
def main():
try:
clt = mqtt.Client()
print(" Client created successfully \n")
clt.on_connect = on_connect
clt.on_message = on_message
clt.connect(brocker,port)
clt.loop_start()
clt.subscribe(topic)
time.sleep(4)
#print("subscribtion: successful \n")
clt.loop_stop()
except Exception as inst:
print("\n Exception found \n")
print(type(inst))
print(inst.args)
print(inst)
print("\n")
main()
and this is the output when I run the publisher script
Client created successfully
Client connected
on_publish callback mid: 1
The message published is: MessageToEncrypt
Encrypted msg: b'c\xf1\x9b\xfca\x081\x8e\xa1+\xe9t\x96\xdei\xdb'
<class 'bytes'>
The publish result is : (0, 1)
client disconnected
Please don't hesitate if you have any suggestion that can help.
Thank you in advance
Both your publisher and subscriber are generating different random key + iv
So there is no way your subscriber can successfully decrypt the message as it doesn't have the right key + iv
So what you get out of the decrypt function is just garbage random noise which is no way guaranteed to be valid utf-8
The subscriber needs to have the same key + iv as the publisher.
This has nothing to do with MQTT

Generating RSA and writing to file

why do i get exception in this code:
I get output:
[*] Error creating your key
[*] Error creating your key
import os, hashlib
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
raw_key = RSA.generate(2048)
private_key = raw_key.exportKey('PEM')
try:
with open('master_private.pem', 'w+') as keyfile:
keyfile.write(private_key)
keyfile.close()
print ("[*] Successfully created your MASTER RSA private key")
except:
print ("[*] Error creating your key")
make_public = raw_key.publickey()
public_key = make_public.exportKey('PEM')
try:
with open("master_public.pem", "w+") as keyfile:
keyfile.write(public_key)
keyfile.close()
print ("[*] Successfully created your MASTER RSA public key")
except:
print ("[*] Error creating your key")
File is created successfully but it is not filled with anything. I am just starting Python.
you should catch exeception and show to know the problem, but i think your problem is the write method, private_key its bytes but you must be pass a str to write method them you can try:
keyfile.write(private_key.decode())
other problem could be your permission permissions, mabe not have permission to create a file, try catching the excaption and printing to know what happen
try:
with open('master_private.pem', 'w+') as keyfile:
keyfile.write(private_key)
keyfile.close()
print ("[*] Successfully created your MASTER RSA private key")
except Exception as e:
print ("[*] Error creating your key", e)
also check your syntax why that code is not well tried

Only byte strings can be passed to C code. python paramiko

I have a simple client-server program that uses python Paramiko.
The client sends an encrypted string to the server and the server needs to decrypt it to process it.
This is the client:
def collect_stats():
try:
cpu = psutil.cpu_percent(interval=1)
memory = psutil.virtual_memory().percent
disk = psutil.disk_usage('/').percent
str_to_send_back = "{} {} {}".format(cpu, memory, disk).strip()
str_to_send_back = str_to_send_back.encode()
str_to_send_back = encrypt(str_to_send_back)
print(str_to_send_back)
The server picks up the string and tries to decode it (at the bottom of this code snipper):
class server:
command='cd %temp% && cd' # Necessary to pull client temp directory path
run_client_script = 'cd %temp% && python client.py' # To run client script
def __init__(self, client_ip, cliet_port, username, password):
self.client_ip = client_ip
self.cliet_port = cliet_port
self.username = username
self.password = password
self.ssh = ssh(self.client_ip, self.username, self.password)
def upload_script_and_get_stats(self):
try:
# Built temp directory path for client machine
client_temp_dir_location = str(self.ssh.send_command(self.command)).strip()
# Client script file name
file_name = "\\client.py"
# Build absolute path of source file
source_file_location = os.path.dirname(os.path.abspath(__file__)) + file_name
# Build absolute path of destination file
destination_file_location = client_temp_dir_location + file_name
# Upload client script
ftp_client = self.ssh.open_sftp(source_file_location, destination_file_location)
# Run client script and get result
result = self.ssh.send_command(self.run_client_script)
# SERVER DECODES STRING HERE
result = self.decrypt(result)
return str(result)
except Exception as e:
print("Oops this error occured in transfer_files_to_client(): " + str(e))
finally:
self.ssh.close()
def decrypt(self, ciphertext):
try:
print(ciphertext)
obj2 = AES.new(b'This is a key123', AES.MODE_CFB, b'This is an IV456')
return obj2.decrypt(ciphertext)
except Exception as e:
print("FDSDSFDSF: "+str(e))
However, the decode method in server throws this error:
FDSDSFDSF: Only byte strings can be passed to C code
However what gets passed to the method is this:
b'\xb5\xf7\xbc\xd5\xfc\xff;\x83\xd3\xab\xb1mc\xc3'
which is already encoded.
Your ciphertext is a string that contains the string representation of a bytes object. I assume your server and client are running on Python 3 and so
print(str_to_send_back)
in the client just prints the representation of the bytes object to standard output. Try using some string friendly encoding for your bytes, such as base64:
from base64 import b64encode
def collect_stats():
try:
...
# str_to_send_back is actually bytes
# Decode the bytes that contain ASCII text for printing
print(b64encode(str_to_send_back).decode('ascii'))
and decode in the receiving end:
from base64 import b64decode
def decrypt(self, ciphertext):
# Removed the over eager "exception handling". The traceback is a
# lot more informative and useful. Add *specific* exception handling
# as necessary
aes = AES.new(b'This is a key123', AES.MODE_CFB, b'This is an IV456')
return aes.decrypt(b64decode(ciphertext))

Python 3 - Socket Chat Encryption with PyCrypto gives UnicodeDecodeError

I am trying to setup a socket chat with encryption in Python 3, but when decoding UTF-8 it gives an error.
Here is the code:
Client:
from Crypto.Cipher import AES
from Crypto import Random
import socket, sys
host = 'localhost'
port = 5558
IV = Random.new().read(16)
c = AES.new('abcd1234efgh5678', AES.MODE_CFB, IV)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
data = 'hey'.encode('utf-8') # 1
data = c.encrypt(data) # 2
s.sendall(data)
Server:
from Crypto.Cipher import AES
from Crypto import Random
import socket, sys
host = ''
port = 5558
IV = Random.new().read(16)
c = AES.new('abcd1234efgh5678', AES.MODE_CFB, IV)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host,port))
s.listen(10)
sock, addr = s.accept()
data = sock.recv(512)
data = c.decrypt(data) # 1
data = data.decode('utf-8') # 2
print(data)
After running these programs the server gives this error:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa5 in position 0: invalid start byte
So, I tried changing 'utf-8' in the Server code to 'latin-1' and it instead kept printing different unicode characters each time the program was run. I then swapped the 2 lines marked with comments in both the client and server, and of course it gave this error:
AttributeError: 'bytes' object has no attribute 'encode'
I have tried Google but all of the programs that use PyCrypto use Python 2, not 3. Eg. Encrypt & Decrypt using PyCrypto AES 256
http://eli.thegreenplace.net/2010/06/25/aes-encryption-of-files-in-python-with-pycrypto/
apart from the fact that your code above uses // as comments (should be #), i ran the code below (removed everything socket) and found the error: you re-initialize the IV before decrypting. this way you will not get the original value back - just some gibberish that may not be decodable in utf-8.
you will have to send the IV to the server (How to communicate AES initialization Vector to client for hybrid cryptosystem).
from Crypto.Cipher import AES
from Crypto import Random
# CLIENT -----------------------------------------
IV = Random.new().read(16)
c = AES.new('abcd1234efgh5678', AES.MODE_CFB, IV)
data = 'hey'.encode('utf-8') # 1
data = c.encrypt(data) # 2
# SERVER -----------------------------------------
# THIS IS WHERE YOUR CODE GOES WRONG!
# IV = Random.new().read(16)
c = AES.new('abcd1234efgh5678', AES.MODE_CFB, IV)
data = c.decrypt(data) # 1
data = data.decode('utf-8') # 2
print(data)

AES encrypted File transfer over TCP socket; padding issue

I'm trying to do a file transfer using encrypted TCP socket with AES 256.
If I transfer a file without encryption, it works fine.
If I send small commands (such as 'ipconfig') to the client or server, the encryption works fine.
No matter the file size is, I keep receiving the following error message:
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
File "/usr/lib/python2.6/base64.py", line 76, in b64decode
raise TypeError(msg)
TypeError: Incorrect padding
My function for encoding and decoding is the following (the hat variable is the message):
def AESENC(hat,typ):
BLOCK_SIZE = 32
PADDING = '{'
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
secret = '01234567890123456789012345678912'
IV = 'wir&/>H54mgd9a";'
cipher = AES.new(secret,AES.MODE_CFB,IV)
if typ == 0:
encoded = EncodeAES(cipher, hat)
return encoded
else:
decoded = DecodeAES(cipher, hat)
return decoded
Client side
if os.path.exists(df):
print ' found the file '
f = open(df, 'rb')
packet = f.read(1024)
while packet != '':
s.send(AESENC(packet,0))
s.send( AESENC('123XXX',0) )
s.send('123XXX')
f.close()
Server side
f = open('/root/Desktop/Transfer.mp3','wb')
while True:
bits = AESENC ( conn.recv(1024) , 1 )
while (bits):
f.write(bits)
bits = AESENC ( conn.recv(1024) , 1 )
if bits.endswith('123XXX'):
print '[+] Transfer completed '
break
f.close()
break
return
Does anybody know how to fix this?
Apologies for the misunderstanding of your sample code, and thank you for adding the server and client calls!
Please note that the error message that you're getting is unrelated to the encryption. You can read the relevant part of the base64.py library: the error message indicates that the base64 data is not valid. In particular, it's not properly padded at the end.
With the additional call site information, I believe the problem is that you're encrypting and then separately encoding each 1024 byte block of the data on the client. Then, on the server, you're reading 1024 bytes from the network and trying to decode it. However, base64-encoding will increase the length of the original data, so what you'll read will only be the first 1024 bytes of the encoded form, which will be a truncated base64 message (hence improperly padded).
As for how to solve it, a base64 message needs to be decoded all as one piece. So you either need to calculate how much data to read from the network to get a complete encoded block (a calculation that you can do reliably except for the possibly short last packet, since the base64 length is always (length + 2) / 3 * 4), encode the entire data stream at once (which is likely a problem due to memory use if you want to handle arbitrary-sized files), or define your network protocol so that the server can tell that it's seen a complete block that can be decoded with base64.

Categories