Python3 Incorrect AES key length (256 bytes) - python

I want to write a script that encrypts the content of a text file (key.k3y). When i execute it, i get the error: Incorrect AES key length (256 Bytes). Obviously that should not be invalid for AES. here is my code:
import base64
import pycryptodome
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
# Set a password and encode it (to Byte type)
password_provided = "NHW!He2-vxxYWF7va23LzjnqFTyvP#dAPGHChXmmSY4YYzJ*HDX_HzRZ-7M8c*2t" #64chars
password = password_provided.encode()
print(len(password))
# Set the hashing parameters for the pw hashing
salt = b'\x08\xfc\xe4e\x89\xc2\xa8\xfe\xe2UsS\xbb#\xbe\x8d\xec\x9b\xb1\xf9\x9d]\xa6D?\xc7\x89\x1b\xdf\xb7\xa3\x19m\x13\xca"i\xbbd\x07b\x8al\x80#xm>Coa\xcc\x88X\xc7#\x99\xd5\xf8\xcf\x86\x04\xbf9'
kdf = PBKDF2HMAC(
algorithm=hashes.SHA512(),
length=192,
salt=salt,
iterations=100000,
backend=default_backend()
)
# Hash and encode the key with SHA512 and base64
key = base64.urlsafe_b64encode(kdf.derive(password))
print("The key (hashed pw) is: ")
print(len(key))
# Get the message or, as in this case, the content of the file key.k3y
messagefile = open('key.k3y', 'rb')
data = messagefile.read()
messagefile.close()
# Encrypting the message with AES, mode CBC
cipher = AES.new(key, AES.MODE_CBC)
encdata = cipher.encrypt(pad(data, AES.block_size))
print(encdata)

Related

Python Incorrect AES key length despite passing the a 32 bytes bytearray

I have a specific AES key that I have to work with which is 10h,10h,10h,"A",10h,10h,10h,"AAA",10h,10h,10h,10h,10h,10h,10h,10h,10h,"A",10h,"A",10h,10h,"AA",10h,"A",10h,"A",10h,"A"
I have to use this key to encrypt a message. In python I covert it to "\x10,\x10,\x10,A,\x10,\x10,\x10,AAA,\x10,\x10,\x10,\x10,\x10,\x10,\x10,\x10,\x10,A,\x10,A,\x10,\x10,AA,\x10,A,\x10,A,\x10,A" but I get ValueError: Incorrect AES key length (60 bytes).
I tried encoding the key in a different way like key = bytearray("\x10,\x10,\x10,A,\x10,\x10,\x10,AAA,\x10,\x10,\x10,\x10,\x10,\x10,\x10,\x10,\x10,A,\x10,A,\x10,\x10,AA,\x10,A,\x10,A,\x10,A".encode('utf-8')) but I still get a same key length error.
What can I do in this case?
This is my code:
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
msg = b"<input><type=\"update\"/></input>"
key = bytearray("\x10,\x10,\x10,A,\x10,\x10,\x10,AAA,\x10,\x10,\x10,\x10,\x10,\x10,\x10,\x10,\x10,A,\x10,A,\x10,\x10,AA,\x10,A,\x10,A,\x10,A".encode('utf-8'))
print(key)
cipher = AES.new(key, AES.MODE_GCM)
encrypted_msg = cipher.encrypt(msg)
print(encrypted_msg)
How about using bytes instead?
#pip install pycryptodome
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
msg = b"<input><type=\"update\"/></input>"
key = bytearray(b"\x10\x10\x10A\x10\x10\x10AAA\x10\x10\x10\x10\x10\x10\x10\x10\x10A\x10A\x10\x10AA\x10A\x10A\x10A")
print(key)
cipher = AES.new(key, AES.MODE_GCM)
encrypted_msg = cipher.encrypt(msg)
print(encrypted_msg)
This seems to be working.
Please note that you can also use bytes.fromhex, which is more readable
#pip install pycryptodome
from Crypto.Cipher import AES
msg = b"<input><type=\"update\"/></input>"
key = bytearray(bytes.fromhex("1010104110101041414110101010101010101041104110104141104110411041"))
print(key)
cipher = AES.new(key, AES.MODE_GCM)
encrypted_msg = cipher.encrypt(msg)
print(encrypted_msg)
Now, the good question: why does this happen?
Well, utf-8 encodes the non ascii characters differently, pseudocode:
'\x80 \x81 \x82 \x83 \x84 \x85 \x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa0 \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf '.encode()
b'\xc2\x80\xc2\x81\xc2\x82\xc2\x83\xc2\x84\xc2\x85\xc2\x86\xc2\x87\xc2\x88\xc2\x89\xc2\x8a\xc2\x8b\xc2\x8c\xc2\x8d\xc2\x8e\xc2\x8f\xc2\x90\xc2\x91\xc2\x92\xc2\x93\xc2\x94\xc2\x95\xc2\x96\xc2\x97\xc2\x98\xc2\x99\xc2\x9a\xc2\x9b\xc2\x9c\xc2\x9d\xc2\x9e\xc2\x9f\xc2\xa0\xc2\xa1\xc2\xa2\xc2\xa3\xc2\xa4\xc2\xa5\xc2\xa6\xc2\xa7\xc2\xa8\xc2\xa9\xc2\xaa\xc2\xab\xc2\xac\xc2\xad\xc2\xae\xc2\xaf\xc2\xb0\xc2\xb1\xc2\xb2\xc2\xb3\xc2\xb4\xc2\xb5\xc2\xb6\xc2\xb7\xc2\xb8\xc2\xb9\xc2\xba\xc2\xbb\xc2\xbc\xc2\xbd\xc2\xbe\xc2\xbf'

encrypting a file and storing the passwoed hash and salt in the same file

am trying to store the password hash and the password salt in the same file that i've encrypted
i tried to write them in the beginning of the file but when i checked if the they were the same before and after wrting it to the file and the answer was they weren't
any help please
this is the function which encrypte the file
def encrypte(self):
global pic_path,getOpenFileName
from cryptography.fernet import Fernet
import base64
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
password_provided = self.pass_entry1.text()
pass_hash=hashlib.sha256(password_provided.encode('utf-8'))
password = password_provided.encode() # Convert to type bytes
salt =bytes(os.urandom(16))
print("salt: "+str(salt))
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
backend=default_backend()
)
key = base64.urlsafe_b64encode(kdf.derive(password))
file = open(pic_path,'rb+')
fdata=file.read()
f = Fernet(key)
encrypted = f.encrypt(fdata) # Encrypt the bytes. The returning object is of type bytes
file.close()
try:
os.mkdir(os.getcwd()+"/encrypted")
except:
pass
pic_path=os.getcwd()+"/encrypted/"+name
fileencrypted=open(os.path.splitext(pic_path)[0]+'.cod','ab+')
fileencrypted.write(salt)
fileencrypted.write(pass_hash.digest())
fileencrypted.write(encrypted)
fileencrypted.close()
self.error_label.setText("file encrypted scessfully")
and this is the function which i used to check if the salt is the same
def decrypte(self):
file= open(filename,'rb')
salt= file.read(16)
print("file salt:"+str(salt))

AES encrypt in Cryptojs, decrypt in Pycrypto

I've tried md5 and sha256 when converting key to 16 bit but after encrypting, the result doesnt work if I'm going to validate it via third party decryptor https://www.browserling.com/tools/aes-decrypt
My goal is to decrypt the js version using python.
Added another link for js version.
https://jsfiddle.net/korvacs/4obfkxm7/17/
Python code:
from Crypto.Cipher import AES
from Crypto import Random
import hashlib
from base64 import b64encode
key = "lazydog".encode("utf-8")
key = hashlib.sha256(key).digest()
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
msg = iv + cipher.encrypt('Attack at dawn')
print(b64encode(msg).decode('utf-8'))
Can someone help me? I'm not really good in encryptions.
I am using PBKDF2 to generate IV and key. This is good practice. We don't need to transfer IV:
Javascript:
let password = "lazydog";
let salt = "salt";
let iterations = 128;
let bytes = CryptoJS.PBKDF2(password, salt, { keySize: 48, iterations: iterations });
let iv = CryptoJS.enc.Hex.parse(bytes.toString().slice(0, 32));
let key = CryptoJS.enc.Hex.parse(bytes.toString().slice(32, 96));
let ciphertext = CryptoJS.AES.encrypt("Attack at dawn", key, { iv: iv });
console.log(ciphertext.toString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script>
Python:
from base64 import b64decode
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
data = b64decode("ibirgCQu8TwtJOaKKtMLxw==")
bytes = PBKDF2("lazydog".encode("utf-8"), "salt".encode("utf-8"), 48, 128)
iv = bytes[0:16]
key = bytes[16:48]
cipher = AES.new(key, AES.MODE_CBC, iv)
text = cipher.decrypt(data)
text = text[:-text[-1]].decode("utf-8")

python decrypt AES

This is my code:
from Crypto.Cipher import AES
from Crypto import Random
import base64
Plain_text = "Text"
random = Random.new()
IV = random.read(AES.block_size)
KEY = base64.b64encode(random.read(AES.key_size[0]))
Cipher = AES.AESCipher(KEY, AES.MODE_CFB, IV)
print "Key:", KEY
Encrypting = Cipher.encrypt(Plain_text)
print "Encrypting:\n",Encrypting
#KEY2 = base64.b64decode(KEY)
#IV2 = random.read(AES.block_size)
#print "KEY2:", KEY2
Cipher2 = AES.AESCipher(base64.b64decode(KEY), AES.MODE_CFB, IV)
Decrypting = Cipher2.decrypt(Encrypting)
print "Decrypting:\n", Decrypting
Script output:
Output is:
Key: VYy9unePPuKiQHwVcqkJzA==
Encrypting:
�F!C
Decrypting:
���
Why script can not decrypt?
OS = Ubuntu 16.04
Python Version = 2.7.12
The key supplied to the AES function should be in binary format. In your case you are encoding the key to base-64 first. In the encryption, it seems that you accidentally use this encoded string as the key.
Fixed code snippet:
from Crypto.Cipher import AES
from Crypto import Random
import base64
plaintext = "Text"
random = Random.new()
iv = random.read(AES.block_size)
key = random.read(AES.key_size[0])
cipher = AES.AESCipher(key, AES.MODE_CFB, iv)
key_b64 = base64.b64encode(key)
print ("Key: {}".format(key_b64))
ciphertext = cipher.encrypt(plaintext)
print("Encrypting: {}".format(ciphertext))

Unable to decrypt using Blowfish

I am using Python3 and PyCrypto module for Blowfish Algorithm. I am able to encrypt when i give the key and plaintext via command line but i am unable to decrypt. However, the code is working correctly if I use it in Python Interpreter.
ENCRYPTION (blowfish_encr.py)
from Crypto.Cipher import Blowfish
from Crypto import Random
from struct import pack
import sys
bs = Blowfish.block_size
key = sys.argv[1].encode()
iv = Random.new().read(bs)
cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv)
plaintext = sys.argv[2].encode()
plen = bs - divmod(len(plaintext),bs)[1]
padding = [plen]*plen
padding = pack('b'*plen, *padding)
msg = iv + cipher.encrypt(plaintext + padding)
print(msg)
DECRYPTION (blowfish_decr.py)
from Crypto.Cipher import Blowfish
from struct import pack
import sys
bs = Blowfish.block_size
ciphertext = sys.argv[2].encode()
key = sys.argv[1].encode()
iv = ciphertext[:bs]
ciphertext = ciphertext[bs:]
cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv)
msg = cipher.decrypt(ciphertext)
last_byte = msg[-1]
msg = msg[:- (last_byte if type(last_byte) is int else ord(last_byte))]
print(repr(msg))
OUTPUT:
$python3 blowfish_encr.py key 'Test it!'
b'\xf8\x1eK)\x81?\xa2\x88\x01\x16\x8e\xdc\xe5\xb9\xd8_K\xce\x03\xe4\x88g\xf8\xa1'
$python3 blowfish_decr.py key '\xf8\x1eK)\x81?\xa2\x88\x01\x16\x8e\xdc\xe5\xb9\xd8_K\xce\x03\xe4\x88g\xf8\xa1'
File "blowfish_decr.py", line 12, in <module>
msg = cipher.decrypt(ciphertext)
File "/usr/lib/python3/dist-packages/Crypto/Cipher/blockalgo.py", line 295, in decrypt
return self._cipher.decrypt(ciphertext)
ValueError: Input strings must be a multiple of 8 in length
How to get it decrypted ? I know the error is because when I input the encoded text as a string it converts all the \ to \\ , and when I try sys.argv[2].encode().replace('\\','\') it it doesn't work because \' is a string literal.
How to get it done using the command line argument?

Categories