Unable to decrypt using Blowfish - python

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?

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'

Python3 Incorrect AES key length (256 bytes)

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)

How can I convert string variable into byte type in python? [duplicate]

This question already has answers here:
Best way to convert string to bytes in Python 3?
(5 answers)
Closed 4 years ago.
I want to encrypt a messages which I got from user input using Cryptography:
I have the following simple code:
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
backend = default_backend()
messages = input("Please, insert messages to encrypt: ")
key = os.urandom(24)
print(key)
cipher = Cipher(algorithms.TripleDES(key), modes.ECB(), backend=backend)
encryptor = cipher.encryptor()
cryptogram = encryptor.update(b"a secret message") + encryptor.finalize()
print(cryptogram)
When I hard code the messages "a secret message" with b prefix in the code it works fine.
What I wanted to do is to use messagesvariable to get the text from user input.
messages = input("Please, insert messages to encrypt: ")
I've tried several ways to covert the string type from the input to byte type and pass it to encryptor.update method but nothing works for me.
messages = input(b"Please, insert messages to encrypt: ")
cryptogram = encryptor.update(byte, message) + encryptor.finalize()
...
Versions:
Python 3.7.0
Cryptography 2.4
Mac OS
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Oct 2 13:23:27 2018
#author: myhaspl
#email:myhaspl#myhaspl.com
#blog:dmyhaspl.github.io
"""
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
padder = padding.PKCS7(128).padder()
backend = default_backend()
key = os.urandom(32)
iv = os.urandom(16)
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
encryptor = cipher.encryptor()
messages = input("Please input your message: ")
messages=bytes(messages,"utf-8")
padded_data = padder.update(messages )
padded_data += padder.finalize()
print(padded_data)
ct = encryptor.update(padded_data) + encryptor.finalize()
decryptor = cipher.decryptor()
decryptorData=decryptor.update(ct) + decryptor.finalize()
unpadder = padding.PKCS7(128).unpadder()
data = unpadder.update(decryptorData)
print(data + unpadder.finalize())
Please input your message: hello,world! I am dmyhaspl.my blog is dmyhaspl.github.io
b'hello,world! I am dmyhaspl.my blog is dmyhaspl.github.io\x08\x08\x08\x08\x08\x08\x08\x08'
b'hello,world! I am dmyhaspl.my blog is dmyhaspl.github.io'
>>>
s = 'a secret message'
b = s.encode('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))

Problems with encryption when converting Crypt:CBC example from Perl to Python (Blowfish)

I am trying to translate the program below to Python.
In the end the Python code should produce the same passphrase output as the Perl variant.
#!/usr/bin/env perl
use Crypt::CBC;
my $key = 'key to the gates';
my $cipher = Crypt::CBC->new(
-key => $key,
-cipher => 'Blowfish',
-salt => '12341234'
);
my $pass_phrase = "secret text";
print $cipher->encrypt_hex($pass_phrase),"\n";
print unpack('H*', $cipher->key()), "\n";
print unpack('H*', $cipher->iv()), "\n";
print unpack('H*', $cipher->salt()), "\n";
print unpack('H*', $cipher->keysize()), "\n";
#output:
#pass:53616c7465645f5f31323334313233344c0ad60f0eb9fdffc46b5cc02d76d473 <- hex enc "Salted__12341234<gibberish>"
#key:031f2cc96d063cf836ce42c77a8a3d25bdd959659d00a892a02b13930e92f47c82a7054256be4a0f1b3771bd36c07fe3ea4f6900f8ddebe5
#iv:f4d50b2385a2a996
#salt:3132333431323334
#keysize:3536
Below is my python code than that decrypts successfully, but encrypts unsuccessfully.
The successfull decryption of the perl passphrase was mostly for verify input params. (Taking IV straight from perl and removing Crypt::CBC's added 16 char of salt before decrypting made it work, various posts on SO helped me..).
Then is the unsuccessful attempt to encryption passhphrase and generate the same output as perl.
I think i just need to use the right combination of the verified input params to get it working...maybe the salt should be padded? Or padding in general is wrong? Or iv input should not be hexlified? (it need to be 8 chars..)
Any input is appreciated!
!/usr/bin/env python
from Crypto.Cipher import Blowfish
from binascii import hexlify, unhexlify
from struct import pack
import base64
# working decryption
passphrase = unhexlify("53616c7465645f5f31323334313233344c0ad60f0eb9fdffc46b5cc02d76d473"[32:])
key = unhexlify("031f2cc96d063cf836ce42c77a8a3d25bdd959659d00a892a02b13930e92f47c82a7054256be4a0f1b3771bd36c07fe3ea4f6900f8ddebe5")
iv = unhexlify('f4d50b2385a2a996')
num_padding = ord(Blowfish.new(key, Blowfish.MODE_CBC, iv).decrypt(passphrase)[-1])
print Blowfish.new(key, Blowfish.MODE_CBC, iv).decrypt(passphrase)[:(-1*num_padding)]
# --- non working encryption!
passphrase2 = "secret text"
key2 = 'key to the gates'
iv2 = unhexlify('f4d50b2385a2a996')
plength = Blowfish.block_size - len(passphrase2) % Blowfish.block_size
padding = [plength] * plength
pad_str = passphrase2 + pack('b' * plength, *padding)
cipher = Blowfish.new(key2, Blowfish.MODE_CBC, iv2)
print hexlify("Salted__12341234"+cipher.encrypt(pad_str))
#output:
#secret text
#53616c7465645f5f31323334313233346aa3f2169677cbf282b1330b46da3114
I guess you are not supposed to answer your own question, but i leave it here anyway:)
I think maybe padding was off in the original code, not really sure.
This time i used the nice "Padding" lib https://pypi.python.org/pypi/Padding
from Crypto.Cipher import Blowfish
from binascii import hexlify, unhexlify
import Padding
class BlowFishCipher:
def __init__( self, key,iv,salt ):
self.key = unhexlify(key)
self.iv = unhexlify(iv)
self.salt = unhexlify(salt)
def encrypt( self, raw ):
raw = Padding.appendPadding(raw, BS)
cipher = Blowfish.new( self.key, Blowfish.MODE_CBC, self.iv )
return hexlify("Salted__"+self.salt+cipher.encrypt(raw))
def decrypt( self, enc):
enc = unhexlify(enc)
cipher = Blowfish.new(self.key, Blowfish.MODE_CBC, self.iv )
return Padding.removePadding(cipher.decrypt( enc), BS)
if __name__== "__main__":
BS = Blowfish.block_size
key_perl = "031f2cc96d063cf836ce42c77a8a3d25bdd959659d00a892a02b13930e92f47c82a7054256be4a0f1b3771bd36c07fe3ea4f6900f8ddebe5"
iv_perl = "f4d50b2385a2a996"
salt_perl= "3132333431323334"
passphrase_perl = "53616c7465645f5f31323334313233344c0ad60f0eb9fdffc46b5cc02d76d473"
# remove "Salted__12341234" from passhphrase_perl by [32:]
passphrase = passphrase_perl[32:]
decryptor = BlowFishCipher(key_perl,iv_perl,salt_perl)
plaintext = decryptor.decrypt(passphrase)
print "decrypted {:>70}".format(plaintext)
ciphertext = "secret text"
encodedtext = decryptor.encrypt(ciphertext)
print "encrypted pyhton {:>70}".format(encodedtext)
print "encrypted perl {:>70}".format(passphrase_perl)
decrypted secret text
encrypted pyhton 53616c7465645f5f31323334313233344c0ad60f0eb9fdffc46b5cc02d76d473
encrypted perl 53616c7465645f5f31323334313233344c0ad60f0eb9fdffc46b5cc02d76d473

Categories