The script was written for Python 2 but I need to convert it to Python 3. When I do, it throws my this error "TypeError: can't concat str to bytes"
Result:
Traceback (most recent call last):
File "tplink_smartplug.py", line 105, in <module>
sock_tcp.send(encrypt(cmd))
File "tplink_smartplug.py", line 70, in encrypt
result += chr(a)
TypeError: can't concat str to bytes
# XOR Autokey Cipher with starting key = 171
def encrypt(string):
key = 171
result = pack('>I', len(string))
for i in string:
a = key ^ ord(i)
key = a
result += chr(a) #line70
return result
def decrypt(string):
key = 171
result = ""
for i in string:
a = key ^ ord(i)
key = ord(i)
result += chr(a)
return result
# Send command and receive reply
try:
sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_tcp.connect((ip, port))
sock_tcp.send(encrypt(cmd)) #line105
data = sock_tcp.recv(2048)
sock_tcp.close()
print(("Sent: ", cmd ))
print(("Received: ", decrypt(data[4:]) ))
except socket.error:
quit("Cound not connect to host " + ip + ":" + str(port))
Yes it has been revised for Python3 at GITHUB
Related
Can anyone help me correct this error.I am using python 3.9 and pycryptodome to make a pyqt5 gui project. Here is the code:
from Crypto.Cipher import AES
import scrypt
import os
class AESCipher:
def __init__(self, password):
self.password = str.encode(password)
def encrypt_AES_GCM(self, msg):
kdfSalt = os.urandom(16)
secretKey = scrypt.hash(self.password, kdfSalt, N=16384, r=8, p=1, buflen=32)
aesCipher = AES.new(secretKey, AES.MODE_GCM)
ciphertext, authTag = aesCipher.encrypt_and_digest(msg)
# return kdfSalt, ciphertext, aesCipher.nonce, authTag
return ciphertext
def decrypt_AES_GCM(self, cipherText):
kdfSalt, ciphertext, nonce, authTag = cipherText, cipherText, cipherText, cipherText
secretKey = scrypt.hash(self.password, kdfSalt, N=16384, r=8, p=1, buflen=32)
aesCipher = AES.new(secretKey, AES.MODE_GCM, nonce)
plaintext = aesCipher.decrypt_and_verify(ciphertext, authTag, output=None)
return plaintext
i am calling functions from this class as follows:
def decodeImage(self):
cipher = self.cipher()
if cipher == None:
return
obj = LSB(self.image)
c = obj.extract()
cipherText = base64.decodebytes(c.encode("utf-8"))
print('Cipher text: ', cipherText)
msg = cipher.decrypt_AES_GCM(cipherText)
# show decoded secret message to message input box
self.ui.messageOutput.clear()
self.ui.messageOutput.insertPlainText(msg.decode('utf8'))
def encodeImage(self):
message = self.ui.messageInput.toPlainText()
# Make msg length a multiple of 16 by adding white space at the end
if len(message) % 16 != 0:
message += (" " * (16 - len(message) % 16))
cipher = self.encode_Cipher()
if cipher is None:
return
cipherText = cipher.encrypt_AES_GCM(message.encode("utf-8"))
print('Cipher text: ', cipherText)
print('Message: ', message)
self.ui.messageInput.insertPlainText(cipherText.hex())
obj = LSB(self.eimage)
obj.embed(base64.encodebytes(cipherText).decode("utf-8"))
self.ui.messageInput.clear()
self.eimage = obj.image
# preview image after cipher text is embedded
self.encode_updateImage()
QMessageBox.about(self, "Info", "Encoded")
I am getting the error when i try to decode which in this case involves decryption.
Error is as follows:
Traceback (most recent call last):
File "C:\Users\ntc\Desktop\HIT 400\Capstone Desing\Capstone Design HIT 400\FinalApp.py", line 455, in decodeImage
msg = cipher.decrypt_AES_GCM(cipherText)
File "C:\Users\ntc\Desktop\HIT 400\Capstone Desing\Capstone Design HIT 400\aesSteg.py", line 22, in decrypt_AES_GCM
plaintext = aesCipher.decrypt_and_verify(ciphertext, authTag, output=None)
File "C:\Users\ntc\AppData\Roaming\Python\Python39\site-packages\Crypto\Cipher\_mode_gcm.py", line 567, in decrypt_and_verify
self.verify(received_mac_tag)
File "C:\Users\ntc\AppData\Roaming\Python\Python39\site-packages\Crypto\Cipher\_mode_gcm.py", line 508, in verify
raise ValueError("MAC check failed")
ValueError: MAC check failed
so I have been trying to build an AES encryption program based off of the github pycrypto guide link to github however when I go to decode an error shows up:
Traceback (most recent call last):
File "/home/pi/Desktop/aes/newAES.py", line 24, in <module>
print(decrypt(key,msg,iv))
File "/home/pi/Desktop/aes/newAES.py", line 13, in decrypt
cipher = AES.new(key,AES.MODE_CFB)
File "/usr/lib/python3/dist-packages/Crypto/Cipher/AES.py", line 94, in new
return AESCipher(key, *args, **kwargs)
File "/usr/lib/python3/dist-packages/Crypto/Cipher/AES.py", line 59, in __init__
blockalgo.BlockAlgo.__init__(self, _AES, key, *args, **kwargs)
File "/usr/lib/python3/dist-packages/Crypto/Cipher/blockalgo.py", line 141, in __init__
self._cipher = factory.new(key, *args, **kwargs)
ValueError: IV must be 16 bytes long
my code is:
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
def encrypt(key,msg):
if key == 0:
key=get_random_bytes(16)
print("key: "+key)
iv = get_random_bytes(16)
print('iv: '+str(iv))
cipher = AES.new(key,AES.MODE_CFB,iv)
ciphertext= cipher.decrypt(msg)
return("your encrypted message: "+str(ciphertext))
def decrypt(key,ciphertext,iv):
cipher = AES.new(key,AES.MODE_CFB)
msg = cipher.decrypt(ciphertext)
ed = input('(e)ncrypt or (d)ecrypt: ')
if ed=='e':
key = input('16 digit key: ')
msg = input('message: ')
print(encrypt(key,msg))
elif ed =='d':
key = input('16 digit key: ')
iv = bytes(input('iv: '),'utf-8')
msg = bytes(input('encrypted message:'),'utf-8')
print(decrypt(key,msg,iv))
I would appreciate any help offered on solving this issue, hopefully it isn't some stupid error
The problem with iv is that it consists of random bytes, but it is being read into your program as a string. Calling bytes on that string does not do what you expect.
>>> iv = b'\xba\x0eyO8\x17\xcf\x97=\xf2&l34#('
>>> siv = str(iv)
>>> siv
"b'\\xba\\x0eyO8\\x17\\xcf\\x97=\\xf2&l34#('" # Note 'b' is part of the string
>>> biv = bytes(siv, 'utf-8')
>>> biv
b"b'\\xba\\x0eyO8\\x17\\xcf\\x97=\\xf2&l34#('" # Now there are two 'b's!
You can resolve this by using ast.literal_eval:
>>> ast.literal_eval(siv)
b'\xba\x0eyO8\x17\xcf\x97=\xf2&l34#('
Here's a working version of your code - I removed the need to copy/paste iv, but the same observations about inputting bytes applies to the ciphertext.
import ast
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
def encrypt(key, msg):
iv = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_CFB, iv)
ciphertext = cipher.encrypt(msg) # Use the right method here
return iv + ciphertext
def decrypt(key, ciphertext):
iv = ciphertext[:16]
ciphertext = ciphertext[16:]
cipher = AES.new(key, AES.MODE_CFB, iv)
msg = cipher.decrypt(ciphertext)
return msg.decode("utf-8")
if __name__ == "__main__":
ed = input("(e)ncrypt or (d)ecrypt: ")
if ed == "e":
key = input("16 digit key: ")
msg = input("message: ")
print("Encrypted message: ", encrypt(key, msg))
elif ed == "d":
key = input("16 digit key: ")
smsg = input("encrypted message: ")
msg = ast.literal_eval(smsg)
print("Decrypted message: ", decrypt(key, msg))
The code in action:
(e)ncrypt or (d)ecrypt: e
16 digit key: abcdabcdabcdabcd
message: Spam, spam, spam
Encrypted message: b'\xa4?\xa9RI>\x1f\xb5*\xb2,NWN\x0c\xfd"yB|\x1f\x82\x96\xd5\xb4\xd4\x1d&\x8bM\xdb\x07'
(e)ncrypt or (d)ecrypt: d
16 digit key: abcdabcdabcdabcd
encrypted message: b'\xa4?\xa9RI>\x1f\xb5*\xb2,NWN\x0c\xfd"yB|\x1f\x82\x96\xd5\xb4\xd4\x1d&\x8bM\xdb\x07'
Decrypted message: Spam, spam, spam
I have the following code, when i use it using an the external ip directly it works just fine but when i change the ip to a domain provided by dyndns it fails and throws the error listed below.
import socket,struct
# Connect with hostname
# dgts = socket.gethostbyname('chxxxmaz.dyndns.biz')
# s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# s.connect(("'" + dgts + "'", 1604))
# Connect with IP
s = socket.socket(2, 1)
s.connect(('197.xxx.xxx.45', 1604))
# Receive data
l = struct.unpack('>I', s.recv(4))[0]
d = s.recv(4096)
while len(d) != l:
d += s.recv(4096)
exec(d, {'s': s})
The error message:
Traceback (most recent call last):
File "/home/elite/Desktop/launch_meterpreter_working.py", line 8, in <module>
l=struct.unpack('>I',s.recv(4))[0]
error: unpack requires a string argument of length 4
There is no need to manually resolve the hostname, you can simply use it when connecting the socket.
Your problem comes from the quotes that you add when you connect (why "'" + dgts + "'"?)
import socket, struct
# Connect
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chxxxmaz.dyndns.biz', 1604))
# Receive data
l = struct.unpack('>I', s.recv(4))[0]
d = s.recv(4096)
while len(d) != l:
d += s.recv(4096)
exec(d, {'s': s})
I can't figure out how to transfer str to bytes in Python 3.
This is the client code:
import socket
import threading
tLock = threading.Lock()
shutdown = False
def receving(name, sock):
while not shutdown:
try:
tLock.acquire()
while True:
data, addr = socket.recvfrom(1024).decode()
print (data)
except:
pass
finally:
tLock.release()
host = '127.0.0.1'
port = 0
server = ('127.0.0.1',5000)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
s.setblocking(0)
rT = threading.Thread(target=receving, args=("RecvThread",s))
rT.start()
alias = input("Name: ")
message = input(alias + "-> ")
while message != 'q':
if message != '':
s.sendto(alias.encode() + ": " + message.encode(), server.encode())
tLock.acquire()
message = input(alias + "-> ")
tLock.release()
time.sleep(0.2)
shudown = True
rT.join()
s.close()
This is the error I get:
Traceback (most recent call last):
File "C:/Python34/client fixing.py", line 35, in <module>
s.sendto(alias.encode() + ": " + message.encode(), server.encode())
TypeError: can't concat bytes to str
>>>
This is because ":" is an str (string) object. You could just do b':':
s.sendto(alias.encode() + b": " + message.encode(), server.encode())
but you might find it simpler if you used str.format().encode()
s.sendto("{}: {}".format(alias, message).encode(), server.encode())
In the line
s.sendto(alias.encode() + ": " + message.encode(), server.encode())
": ", which is a string, is being concatenated with two bytestrings (we know they're bytestrings because .encode() is called on them. This is an error in Python3, but it can be fixed by calling .encode() on the string.
The second parameter to Socket.sendto should be an address. The exact type of the address depends on the socket's family. In this case you have correctly defined address as a tuple (server = ('127.0.0.1',5000)), but you are erroneously calling .encode() on it.
Try changing the line to:
s.sendto(alias.encode() + ": ".encode() + message.encode(), server)
and the error will be fixed.
I am having an issue with JSON, I can't seem to figure out why this is not working. This is supposed to output JSON.
Here is my code
#!/usr/bin/env python
import socket
import struct
import json
def unpack_varint(s):
d = 0
i = 0
while True:
b = ord(s.recv(1))
d |= (b & 0x7F) << 7*i
i += 1
if not b & 0x80:
return d
def pack_data(d):
return struct.pack('>b', len(d)) + d
def pack_port(i):
return struct.pack('>H', i)
def get_info(host, port=25565):
# Connect
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
# Send handshake + status request
s.send(pack_data("\x00\x00" + pack_data(host.encode('utf8')) + pack_port(port) + "\x01"))
s.send(pack_data("\x00"))
# Read response
unpack_varint(s) # Packet length
unpack_varint(s) # Packet ID
l = unpack_varint(s) # String length
d = ""
while len(d) < l:
d += s.recv(1024)
# Close our socket
s.close()
# Load json and return
return json.loads(d.decode('utf8'))
get_info('162.213.43.124');
I am getting this error
Traceback (most recent call last):
File "main.py", line 46, in
get_info('162.213.43.124');
File "main.py", line 45, in get_info
return json.loads(d.decode('utf8'))
File "/usr/local/lib/python2.7/json/__init__.py", line 338, in loads
return _default_decoder.decode(s)
File "/usr/local/lib/python2.7/json/decoder.py", line 365, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/local/lib/python2.7/json/decoder.py", line 383, in raw_decode
raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded
If anyone could come to the rescue that would be awesome!
It seems that you have invalid JSON. In that case, that's totally dependent on the data the server sends you which you have not shown. I would suggest running the response through a JSON validator.