ValueError: Ciphertext with incorrect length using Python - python-3.x

Can some please help me I tried googling this error but could not understand why it is being raised. Can you point out the problem in my code I am fairly new to encryption this is my first time trying to use it.
session_key = cipher_rsa.decrypt(enc_session_key)
, ValueError("Ciphertext with incorrect length."),
ValueError: Ciphertext with incorrect length.
Encryption code
from Crypto.PublicKey import RSA
from Crypto import Random
from Crypto.Cipher import AES, PKCS1_OAEP
from Crypto.Random import get_random_bytes
random_generator = Random.new().read
print (random_generator,"HI")
key = RSA.generate(1024, random_generator)
print(key)
code = 'totalyundetectable' #******************important ****************
encrypted_key = key.exportKey(format='PEM', passphrase=code, pkcs=8,
protection="scryptAndAES128-CBC")
with open('C:/Users/Arnav/Documents/Project/my_private_key.bin', 'wb') as f:
f.write(encrypted_key)
with open('C:/Users/Arnav/Documents/Project/my_rsa_public.pem', 'wb') as f:
f.write(key.publickey().exportKey())
with open('C:/Users/Arnav/Documents/Project/encrypted_data.bin', 'wb') as out_file:
recipient_key = RSA.import_key(
open('C:/Users/Arnav/Documents/Project/my_rsa_public.pem').read())
session_key = get_random_bytes(16)
cipher_rsa = PKCS1_OAEP.new(recipient_key)
out_file.write(cipher_rsa.encrypt(session_key))
cipher_aes = AES.new(session_key, AES.MODE_EAX)
data = b'blah blah bl'
ciphertext, tag = cipher_aes.encrypt_and_digest(data)
out_file.write(cipher_aes.nonce)
out_file.write(tag)
out_file.write(ciphertext)
code = 'totalyundetectable'
Decryption code
with open('C:/Users/Arnav/Documents/Project/encrypted_data.bin', 'rb') as fobj:
private_key = RSA.import_key(
open('C:/Users/Arnav/Documents/Project/my_private_key.bin','rb').read(),
passphrase=code)
enc_session_key, nonce, tag, ciphertext = [fobj.read(x)
for x in (private_key.size_in_bytes(),
16, 16, -1)]
cipher_rsa = PKCS1_OAEP.new(private_key)
session_key = cipher_rsa.decrypt(enc_session_key)
cipher_aes = AES.new(session_key, AES.MODE_EAX, nonce)
data = cipher_aes.decrypt_and_verify(ciphertext, tag)
print(data)

In your case it looks like wrong white spaces/tabs. Because if I write like:
from Crypto.PublicKey import RSA
from Crypto import Random
from Crypto.Cipher import AES, PKCS1_OAEP
from Crypto.Random import get_random_bytes
random_generator = Random.new().read
print (random_generator,"HI")
key = RSA.generate(1024, random_generator)
print(key)
code = 'totalyundetectable' #******************important ****************
encrypted_key = key.exportKey(format='PEM', passphrase=code, pkcs=8,
protection="scryptAndAES128-CBC")
with open('my_private_key.bin', 'wb') as f:
f.write(encrypted_key)
with open('my_rsa_public.pem', 'wb') as f:
f.write(key.publickey().exportKey())
with open('encrypted_data.bin', 'wb') as out_file:
recipient_key = RSA.import_key(
open('my_rsa_public.pem').read())
session_key = get_random_bytes(16)
cipher_rsa = PKCS1_OAEP.new(recipient_key)
out_file.write(cipher_rsa.encrypt(session_key))
cipher_aes = AES.new(session_key, AES.MODE_EAX)
data = b'blah blah bl'
ciphertext, tag = cipher_aes.encrypt_and_digest(data)
out_file.write(cipher_aes.nonce)
out_file.write(tag)
out_file.write(ciphertext)
code = 'totalyundetectable'
with open('encrypted_data.bin', 'rb') as fobj:
private_key = RSA.import_key(
open('my_private_key.bin','rb').read(),
passphrase=code)
enc_session_key, nonce, tag, ciphertext = [fobj.read(x)
for x in (private_key.size_in_bytes(),
16, 16, -1)]
cipher_rsa = PKCS1_OAEP.new(private_key)
session_key = cipher_rsa.decrypt(enc_session_key)
cipher_aes = AES.new(session_key, AES.MODE_EAX, nonce)
data = cipher_aes.decrypt_and_verify(ciphertext, tag)
print(data)
I'm getting as result:
<bound method _UrandomRNG.read of <Crypto.Random._UrandomRNG object at 0x000001696F4B8700>> HI
Private RSA key at 0x1696FB5CE20
b'blah blah bl'
Also, be careful, if you're using the construction in code without with statement, you need to close file at the end.
E.g. in this case will be the error ValueError: Ciphertext with incorrect length:
#...
out_file = open("encrypted_data.bin", "wb")
recipient_key = RSA.import_key(
open('my_rsa_public.pem').read())
session_key = get_random_bytes(16)
cipher_rsa = PKCS1_OAEP.new(recipient_key)
out_file.write(cipher_rsa.encrypt(session_key))
cipher_aes = AES.new(session_key, AES.MODE_EAX)
data = b'blah blah bl'
ciphertext, tag = cipher_aes.encrypt_and_digest(data)
out_file.write(cipher_aes.nonce)
out_file.write(tag)
out_file.write(ciphertext)
#...
To solve it you need to write like:
#...
out_file = open("encrypted_data.bin", "wb")
recipient_key = RSA.import_key(
open('my_rsa_public.pem').read())
session_key = get_random_bytes(16)
cipher_rsa = PKCS1_OAEP.new(recipient_key)
out_file.write(cipher_rsa.encrypt(session_key))
cipher_aes = AES.new(session_key, AES.MODE_EAX)
data = b'blah blah bl'
ciphertext, tag = cipher_aes.encrypt_and_digest(data)
out_file.write(cipher_aes.nonce)
out_file.write(tag)
out_file.write(ciphertext)
out_file.close() # important to add at the end
#...
Alternatively, you can do:
#...
with open('encrypted_data.bin', 'wb') as out_file:
recipient_key = RSA.import_key(
open('my_rsa_public.pem').read())
session_key = get_random_bytes(16)
cipher_rsa = PKCS1_OAEP.new(recipient_key)
out_file.write(cipher_rsa.encrypt(session_key))
cipher_aes = AES.new(session_key, AES.MODE_EAX)
data = b'blah blah bl'
ciphertext, tag = cipher_aes.encrypt_and_digest(data)
out_file.write(cipher_aes.nonce)
out_file.write(tag)
out_file.write(ciphertext)
#...

Related

Implementing Laravel crypt and decrypt functions in python

I was able to find the decrypt function with a few researches, and now
I am trying to write laravel encrypt function using python.
I can decrypt using it:
class decrypter:
def __init__(cls, key):
cls.key = key
def decrypt(cls, text):
decoded_text = json.loads(base64.b64decode(text))
iv = base64.b64decode(decoded_text['iv'])
crypt_object = AES.new(key=cls.key, mode=AES.MODE_CBC, IV=iv)
decoded = base64.b64decode(decoded_text['value'])
decrypted = crypt_object.decrypt(decoded)
return unpad(decrypted, 16).decode('utf-8')
def decrypt_string(str):
try:
key = b"xxxx+xxxxxx+x+xxxx+xxxxx"
key = base64.b64decode(key)
msg = str
obj = decrypter(key)
decrypted = obj.decrypt(msg)
return decrypted
except Exception as e:
logla.logla(e, "decrypt_string")
print(e)
But I couldn't find a source for the encrypt method. There is a source I could find, but I couldn't run it.
enter link description here
For encryption, proceed in the opposite direction:
Create an IV
Pad plaintext
Save IV and ciphertext to JSON
Encode JSON with Base64
For encryption as in the linked code, additionally the MAC has to be generated and the PHP serialization has to be used:
import json
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
from Crypto.Hash import HMAC, SHA256
from phpserialize import loads, dumps
class encrypter:
def __init__(cls, key):
cls.key = key
def encrypt(cls, text):
text = dumps(text)
msg = pad(text, 16)
iv = get_random_bytes(16) # b'0123456789012345'
crypt_object = AES.new(key=cls.key, mode=AES.MODE_CBC, IV=iv)
encrypted = crypt_object.encrypt(msg)
ivB64 = base64.b64encode(iv)
encryptedB64 = base64.b64encode(encrypted)
mac = HMAC.new(cls.key, digestmod=SHA256).update(ivB64+encryptedB64).hexdigest()
json_string = json.dumps({'iv': ivB64.decode(), 'value': encryptedB64.decode(), 'mac': mac})
return base64.b64encode(json_string.encode())
def encrypt_string(str, key):
try:
msg = str.encode()
obj = encrypter(key)
encrypted = obj.encrypt(msg)
return encrypted
except Exception as e:
print(e)
# Test
keyB64 = b'MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDE='
key = base64.b64decode(keyB64)
plaintext= 'This is a test plaintext'
encrypted = encrypt_string(plaintext, key)
decrypted = decrypt_string(encrypted, key)
print(encrypted)
print(base64.b64decode(encrypted))
For the test-IV b'0123456789012345' the output is:
b'eyJpdiI6ICJNREV5TXpRMU5qYzRPVEF4TWpNME5RPT0iLCAidmFsdWUiOiAiTlE1djFpaWU1QnFoTWNwRlhNdUFSZ2N3YVlrNG5CZlJyYmRKUGRna3FDcUN6NEZ6ZDhSOHhIUy95N1N3TWlQTyIsICJtYWMiOiAiYmYwNGJjMWEyN2NhNWUzMGFlYTdjZTI4Y2FkYTBlZGVjOGEwMzc3NWZhODVhMDc2MGRhODUzNDc1OTBmYmNmZCJ9'
b'{"iv": "MDEyMzQ1Njc4OTAxMjM0NQ==", "value": "NQ5v1iie5BqhMcpFXMuARgcwaYk4nBfRrbdJPdgkqCqCz4Fzd8R8xHS/y7SwMiPO", "mac": "bf04bc1a27ca5e30aea7ce28cada0edec8a03775fa85a0760da85347590fbcfd"}'
The linked code produces the same output using the same plaintext, key, and test-IV.

How to write to text file in python?

I am a beginner in using python. I have created a plain text file and have to encrypt it to output file. But I am getting an error as below and unable to write it to output file. The code is running but the output file which should be encrypted is created.
#!/usr/bin/env python3
import os
import binascii
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
import argparse
def readfile_binary(file):
with open(file, 'rb') as f:
content = f.read()
return content
def writefile_binary(file, content):
with open(file, 'wb') as f:
f.write(content)
def main():
parser = argparse.ArgumentParser(description = 'Encryption and Decryption of the file')
parser.add_argument('-in', dest = 'input', required = True)
parser.add_argument('-out', dest = 'output', required = True)
parser.add_argument('-K', dest = 'key', help = 'The key to be used for encryption must be in hex')
parser.add_argument('-iv', dest = 'iv', help = 'The inintialisation vector, must be in hex')
args = parser.parse_args()
input_content = readfile_binary(args. input)
output_content = writefile_binary(args. output)
if __name__ == "__main__":
main()
The output file should be encrypted and it should be available in the directory.
These two lines:
input_content = readfile_binary(args. input)
output_content = writefile_binary(args. output)
There should not be a space in args.input. Here is an example,
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('filename')
args = parser.parse_args()
# using type hints can help reasoning about code
def write(filename: str, content: str) -> None:
with open(filename, 'wb') as f:
f.write(str.encode(content))
# if the filename was successfully parsed from stdin
if args.filename == 'filename.txt':
print(f"args: {args.filename}")
# write to the appropriate output file
write(filename=args.filename, content="content")
You might need to correct your code's indentation. Python requires indenting code within each function definition, loop, etc.
And as eric points out, there should be no spaces after the periods in args. input and args. output. Change those to args.input and args.output instead.
So:
#!/usr/bin/env python3
import os
import binascii
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
import argparse
def readfile_binary(file):
with open(file, 'rb') as f:
content = f.read()
return content
def writefile_binary(file, content):
with open(file, 'wb') as f:
f.write(content)
def main():
parser = argparse.ArgumentParser(description = 'Encryption and Decryption of the file')
parser.add_argument('-in', dest = 'input', required = True)
parser.add_argument('-out', dest = 'output', required = True)
parser.add_argument('-K', dest = 'key', help = 'The key to be used for encryption must be in hex')
parser.add_argument('-iv', dest = 'iv', help = 'The inintialisation vector, must be in hex')
args = parser.parse_args()
input_content = readfile_binary(args.input)
output_content = writefile_binary(args.output)
if __name__ == "__main__":
main()

Getting Exception: Object type <class 'str'> cannot be passed to C code

I install pip install pycryptodome on Python 3.7.2. I'm getting above exception for obj = AES.new(key, AES.MODE_CBC, iv) line. my code is:
from Crypto import Random
from Crypto.Cipher import AES
import random
def get_encryption():
try:
str = "This is input string"
key = b'abcdefghijklmnop'
iv = Random.new().read(AES.block_size)
obj = AES.new(key, AES.MODE_CBC, iv)
encrypted = obj.encrypt(str)
print(encrypted)
except Exception as e:
print(e)
I tried to all the way but not getting how to solve it.
After tried all the way I got solution. I converted key string into bytes.
code is:
from Crypto import Random
from Crypto.Cipher import AES
import random
def get_encryption():
try:
strmsg = "This is input string"
key = 'abcdefghijklmnop'
key1 = str.encode(key)
iv = Random.new().read(AES.block_size)
obj = AES.new(key1, AES.MODE_CBC, iv)
encrypted = obj.encrypt(str.encode(strmsg))
print(encrypted)
except Exception as e:
print(e)
//First pip install pycryptodome -- (pycrypto is obsolete and gives issues)
// pip install pkcs7
from Crypto import Random
from Crypto.Cipher import AES
import base64
from pkcs7 import PKCS7Encoder
from app_settings.views import retrieve_settings # my custom settings
app_secrets = retrieve_settings(file_name='secrets');
def encrypt_data(text_data):
#limit to 32 bytes because my encryption key was too long
#yours could just be 'abcdefghwhatever'
encryption_key = app_secrets['ENCRYPTION_KEY'][:32];
#convert to bytes. same as bytes(encryption_key, 'utf-8')
encryption_key = str.encode(encryption_key);
#pad
encoder = PKCS7Encoder();
raw = encoder.encode(text_data) # Padding
iv = Random.new().read(AES.block_size )
# no need to set segment_size=BLAH
cipher = AES.new( encryption_key, AES.MODE_CBC, iv )
encrypted_text = base64.b64encode( iv + cipher.encrypt( str.encode(raw) ) )
return encrypted_text;
The easiest way to convert the string to bytes is using the binascii lib:
from binascii import unhexlify, hexlify
def aes_encript(key, msg):
c = unhexlify(key)
m = unhexlify(msg)
cipher = AES.new(c, AES.MODE_ECB)
msg_en = cipher.encrypt(m)
return hexlify(msg_en)

TKINTER: Read file if entries match stored data?

I am new to python, I am trying to create a button function that can both write new data to file and if written data matches then fetch load the data from profile.
The issue I face is here:
line 12: if firstname_info in list_of_files:
code does not run the if statement of the loop - maybe I have made an error with the variable matching the file?
Code:
from tkinter import *
import tkinter.messagebox
import os
def register_user():
firstname_info = firstname.get()
lastname_info = lastname.get()
iden_info = iden.get()
email_info = email.get()
list_of_files = os.listdir()
if firstname_info in list_of_files:
file1 = open(firstname_info, "r")
verify = file1.read().splitlines()
if lastname_info in verify:
if iden_info in verify:
if email_info in verify:
print("it worked")
else:
print("user not found")
def main_screen():
global screen
screen = Tk()
global firstname
global lastname
global iden
global email
firstname = StringVar()
lastname = StringVar()
iden = StringVar()
email = StringVar()
header = Label(text = "Header")
firstname_label = Label(text = "Firstname")
lastname_label = Label(text = "lastname")
iden_label = Label(text = "Student ID")
email_label = Label(text = "Student Email")
header.grid(row=0, column=1)
firstname_label.grid(row=1, column=0)
lastname_label.grid(row=2, column=0)
iden_label.grid(row=3, column=0)
email_label.grid(row=4, column=0)
b1 = Button(text = "Submit", command = register_user)
b1.grid(row = 5, column = 1)
global firstname_entry
global lastname_entry
global iden_entry
global email_entry
firstname_entry = Entry(textvariable = firstname)
firstname_entry.grid(row = 1, column = 1)
lastname_entry = Entry(textvariable = lastname)
lastname_entry.grid(row = 2, column = 1)
iden_entry = Entry(textvariable = iden)
iden_entry.grid(row = 3, column = 1)
email_entry = Entry(textvariable = email)
email_entry.grid(row = 4, column = 1)
screen.mainloop()
main_screen()
thanks
If you run your script in the same directory of the stored data, it should work as os.listdir() will search file in . directory which is current directory. However, it is better to specify the directory of the stored data in os.listdir(), like os.listdir('/path/to/stored/data'). Also, I think the following block of code:
if firstname_info in list_of_files:
file1 = open(firstname_info, "r")
verify = file1.read().splitlines()
if lastname_info in verify:
if iden_info in verify:
if email_info in verify:
print("it worked")
else:
print("user not found")
should be changed to:
if firstname_info in list_of_files:
print('user profile found')
with open(firstname_info, "r") as file1:
verify = file1.read().splitlines()
if lastname_info in verify and iden_info in verify and email_info in verify:
print("it worked")
else:
print("user info incorrect")
else:
print("user profile not found")
You are not writing the data from the GUI to any files.
Before reading from file which is firstname_info you should create it first.
you can modify your register_user() function as below code
def register_user():
firstname_info = firstname.get()
lastname_info = lastname.get()
iden_info = iden.get()
email_info = email.get()
list_of_files = os.listdir()
if firstname_info in list_of_files:
file1 = open(firstname_info, "r")
verify = file1.read().splitlines()
if lastname_info in verify:
if iden_info in verify:
if email_info in verify:
print("it worked")
else:
print("user not found")
else:
file1 = open(firstname_info, "w")
file1.write(lastname_info+"\n"+iden_info+"\n"+email_info)
file1.close()

NameError while calling module, declaring default values in a class function

I'm trying to understand Public Key encryption so I wrote this little module using PyCryptodome and the RSA/PKCS1_OAEP module on Python 3 to help me along. However, I keep getting an error:
NameError: name 'aesenc' is not defined
This is a two part question:
In standalone code (outside a class) the arg = default_val code will work, but I'm pretty sure this code will throw an error (assuming I fix question #2). I also know I can't use self.default_val as that needs an object to be created first. How do I assign a default value (in this case, the private/public key of the object?)
With regard to the error message, a vgrep reveals that the suite has been declared before its been called but I still get the NameError. Can someone please take a look and let me know what I'm doing wrong?
Modules: (Breaking into parts as SO keeps jumbling the code)
from passlib.context import CryptContext
from Crypto.Cipher import AES, PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto import Random
from Crypto.Random import get_random_bytes
The Class:
class statEnc:
pubcipher = None
privcipher = None
pubkeystr = None
privkeystr = None
sessionkey = None
def __init__(self, pubkeystr = None, privkeystr = None, sessionkey = None):
self.pubkeystr = pubkeystr
self.privkeystr = privkeystr
self.sessionkey = sessionkey
if pubkeystr == None or privkeystr == None: #if blank, generate keys
self.random_generator = Random.new().read
self.keys = RSA.generate(1024, self.random_generator)
self.pubkey = self.keys.publickey()
self.pubkeystr = self.pubkey.exportKey(format='PEM',
passphrase=None,
pkcs=1)
self.pubcipher = PKCS1_OAEP.new(self.pubkey)
self.privcipher = PKCS1_OAEP.new(self.keys)
self.privkeystr = self.keys.exportKey(format='PEM',
passphrase=None,
pkcs=1)
self.privkey = self.keys.exportKey()
else: #import the keys
self.pubkey = RSA.importKey(pubkeystr)
self.pubcipher = PKCS1_OAEP.new(pubkey)
self.privkey = RSA.importKey(privkeystr)
self.pubcipher = PKCS1_OAEP.new(privkey)
if sessionkey == None:
sessionkey = get_random_bytes(16)
else:
self.sessionkey = sessionkey
def encrypt_val(self, session_key, cipher = pubcipher):
# a little ditty to hep encrypt the AES session key
try:
session_key = session_key.encode('utf8')
except:
pass
ciphertext = cipher.encrypt(session_key)
return ciphertext
def decrypt_val(self, ciphertext, cipher = privcipher):
# a little ditty to hep decrypt the AES session key
session_key = cipher.decrypt(ciphertext)
try:
session_key = session_key.decode('utf8')
except:
pass
return session_key
def aesenc(self, data, *args):
#encrypt the payload using AES
key = ''
if args:
if 'str' in str(type(args[0])):
try:
key = int(args[0])
except:
key = get_random_bytes(16)
else:
key = get_random_bytes(16)
try:
data = data.encode('utf8')
except:
pass
cipher = AES.new(key, AES.MODE_EAX)
ciphertext, tag = cipher.encrypt_and_digest(data)
aesencdict = {
'ciphertext' : ciphertext,
'tag' : tag,
'nonce' : cipher.nonce ,
'key' : key
}
return(aesencdict)
def aesdec(self, aesdict):
#decrypt the AES encrypted payload
cipher = AES.new(aesdict['key'], AES.MODE_EAX, aesdict['nonce'])
data = cipher.decrypt_and_verify(aesdict['ciphertext'], aesdict['tag'])
try:
data = data.decode('utf8')
except:
pass
return data
def end2enc(self, val, cipher = pubcipher):
# a master function to first encrypt the payload
val = str(val)
encval = aesenc(val)
# and then PK encrypt the key
encval['key'] = encrypt_val(encval['key'], cipher)
return encval
def end2dec(self, encval, cipher = privcipher):
encval['key'] = decrypt_val(encval['key'], cipher)
outval = aesdec(encval['aesdict'], encval['key'])
return outval
Test function and main:
def test():
val = { 'test' : "hello"}
keypair = statEnc()
print(str(type(keypair)))
encval = keypair.end2enc(val, keypair.pubcipher)
outval = keypair.end2dec(encval, keypair.privcipher)
print(val, outval)
if val == eval(outval):
return(val)
else:
return False
if __name__ == '__main__':
test()
[UPDATE]
The Traceback is as follows:
[guha#katana stat]$ python statenc.py
<class '__main__.statEnc'>
Traceback (most recent call last):
File "statenc.py", line 124, in <module>
test()
File "statenc.py", line 115, in test
encval = keypair.end2enc(val, keypair.pubcipher)
File "statenc.py", line 100, in end2enc
encval = aesenc(val)
NameError: name 'aesenc' is not defined
Slept over my question and woke up with a fresh mind, and voila! the answer presented itself.
The answer to the second question is as follows:
2. putting a simple 'self.' solves the problem - i was calling 'aesenc(params)' instead of 'self.aesenc(params)'. Stupid of me, really.
Question 1 is answered in this SO question.

Resources