Encrypting mulitple files with hybrid encryptions, encountering error when decrypting - python

Basically, i am trying to encrypt 3 files in a folder with hybrid encryption, AES CBC. Successfully encrypted all the files, but having issues decrypting. The requirements for the task is:
2 seperate files, one for encrypting and one for decrypting
IV is 24 characters
IV can be hardcoded ,all files can use the same IV in or randomised (i randomised mine)
So far, only the last file is decrypted properly, the first 2 is giving me a ValueError error. However when i printed out the IV, it seems to be correct. Can someone advise me on this?
Encryption code
`#!/usr/bin/env python3
from base64 import b64encode
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Random import get_random_bytes
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import glob
for item in glob.glob("*.txt"):
skey = get_random_bytes(16)
recipent_key = RSA.import_key(open("receiver.pem").read())
file_out = open("encrypted_key.bin", "wb")
cipher_rsa = PKCS1_OAEP.new(recipent_key)
enc_data = cipher_rsa.encrypt(skey)
file_out.write(enc_data)
file_out.close()
data_in = open(item, 'rb')
data = data_in.read()
data_in.close()
cipher = AES.new(skey, AES.MODE_CBC)
ct_bytes = cipher.encrypt(pad(data, AES.block_size))
iv = b64encode(cipher.iv).decode('utf-8')
ct = b64encode(ct_bytes).decode('utf-8')
skey = b64encode(skey).decode('utf-8')
print(iv, ct, skey)
datain = (iv, ct)
Fileout = open(item,'w')
Fileout.writelines(datain)
Fileout.close()
`
Decryption code
`#!/usr/bin/env python3
from base64 import b64decode
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import os
import glob
for item in glob.glob("*.txt"):
file_in = open("encrypted_key.bin", "rb")
private_key = RSA.import_key(open("private.pem").read())
enc_data = file_in.read(private_key.size_in_bytes())
cipher_rsa = PKCS1_OAEP.new(private_key)
skey = cipher_rsa.decrypt(enc_data)
file_in.close()
in_file = open(item, "r")
data = in_file.read()
in_file.close()
print(data[0:24])
try:
iv = b64decode(data[0:24])
ct = b64decode(data[24:])
cipher = AES.new(skey, AES.MODE_CBC, iv)
pt = unpad(cipher.decrypt(ct), AES.block_size)
output = str(pt, 'utf-8')
print("the message was: ", output)
Fileout = open(item,'w')
Fileout.writelines(output)
Fileout.close()
except ValueError:
print("Incorrect decryption")
except KeyError:
print("incorrect key")
`
please send help :"")
EDIT: i realised, every round my loop goes, my key also randomise. that's the problem, i solved it :")

Related

Crypting in python using hashlib

I have this piece of code
import hashlib
from Cryptodome.Cipher import AES
decryption_key = hashlib.sha256(b"050746" + b"\x00\x00\x00\x03").digest()
iv = 16 * b '\x00'
aes = AES.new(decryption_key, AES.MODE_CBC, iv)
decrypted_nonce = aes.decrypt(encrypted_nonce)
I need help in understanding what this code is doing
I would be grateful for your help

Cryptodome AES encrypt and decrypt

I'm struggling to find the issue within the code:
I've txt file on my desktop that i want to encrypt, then decrypt.
I'm using AES CBC as my encryption method.
Assume the file contain the following string:
bla bla top secret!!
I'm able to encrypt it successfully with the following line: modify(r"C:\Users\XXXXX\Desktop\TEST.txt", encrypt_file) output: W¢ìPY#Šÿb[l®«fì]ßQzýµá˺cØäûE
Then I'm trying to decrypt it with the following line modify(r"C:\Users\XXXXX\Desktop\TEST.txt", decrypt_file)
I'm getting the following exception: ValueError: Padding is incorrect.
If I remove the unpad function i can see the text is partical unencrypted as follow: bla bla top secrv€\Èu¢Þ#xH‹AÄ
I can't find whats wrong here.
Any help will be appreciated.
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
HARD_CODED_KEY = b"SOME KEY"
iv = b'1234567812345678'
def encrypt_file(file, key, blocksize=16):
cipher = AES.new(key, AES.MODE_CBC, iv)
ciphertext = cipher.encrypt(pad(file, blocksize))
return ciphertext
def decrypt_file(file, key, blocksize=16):
cipher = AES.new(key, AES.MODE_CBC, iv)
cleartext = unpad(cipher.decrypt(file), blocksize)
return cleartext
def modify(file, crypt, blocksize=16):
with open(file, "r+b") as f:
plaintext = f.read(blocksize)
while plaintext:
ciphertext = crypt(plaintext, HARD_CODED_KEY, blocksize)
f.seek(-len(plaintext), 1) # go back to the same point before the read
f.write(ciphertext)
plaintext = f.read(blocksize)

Incorrect decryption RSA pycryptodome

I try to implement RSA in Python with pycryptodome, the encrypt Works fine but the decrypt function no, my code is the following:
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Signature import pss
from Crypto.Hash import SHA256
class RSA_OBJECT:
def create_KeyPair(self):
self.key = RSA.generate(self.KEY_LENGTH)
def save_PrivateKey(self, file, password):
key_cifrada = self.key.export_key(passphrase=password, pkcs=8,protection="scryptAndAES128-CBC")
file_out = open(file, "wb")
file_out.write(key_cifrada)
file_out.close()
def load_PrivateKey(self, file, password):
key_cifrada = open(file, "rb").read()
self.private_key = RSA.import_key(key_cifrada, passphrase=password)
def save_PublicKey(self, file):
key_pub = self.key.publickey().export_key()
file_out = open(file, "wb")
file_out.write(key_pub)
file_out.close()
def load_PublicKey(self, file):
key_publica = open(file, "rb").read()
self.public_key = RSA.import_key(key_publica)
I don't know why, because I think that the code is correct, anyone can help me?
Your problem you generate two different keys;
self.public_key = RSA.generate(self.KEY_LENGTH)
self.private_key = RSA.generate(self.KEY_LENGTH)
you should;
key = RSA.generate(self.KEY_LENGTH)
and
private_key = key.export_key()
file_out = open("private.pem", "wb")
file_out.write(private_key)
public_key = key.publickey().export_key()
file_out = open("receiver.pem", "wb")
file_out.write(public_key)
See here in more details;
Note: note that key object has two functionality due to public keys encryption. You can write a private key into a file and public key into another. In this way, you can distribute the key. See RSAKey.

Telegram Passport data decryption (Python)

Using https://core.telegram.org/passport#decrypting-data, I've come up with the following function:
import hashlib
from base64 import b64decode
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES
def decode_credentials(credentials):
data_encrypted = b64decode(credentials['data'])
credentials_hash = b64decode(credentials['hash'])
secret_encrypted = b64decode(credentials['secret'])
with open(f"private.key", "r") as f:
private_key = RSA.importKey(f.read())
secret_decrypted = private_key.decrypt(secret_encrypted)
secret_hash = hashlib.sha512(secret_decrypted + credentials_hash).digest()
aes_key = secret_hash[:32]
aes_iv = secret_hash[32:48]
aes = AES.new(aes_key, AES.MODE_CBC, aes_iv)
data_decrypted = aes.decrypt(data_encrypted)
data_decrypted_hash = hashlib.sha256(data_decrypted).digest()
if data_decrypted_hash != credentials_hash:
raise Exception("HASH MISMATCH")
return data_decrypted[data_decrypted[0]:]
Following code always raises HASH MISMATCH for me, hence the question: What's wrong with the code?
Has anybody come up with the working solution that they can share?
The problem was in this lines:
with open(f"private.key", "r") as f:
private_key = RSA.importKey(f.read())
secret_decrypted = private_key.decrypt(secret_encrypted)
I don't know the difference, but the correct is:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.hashes import SHA1
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.padding import MGF1, OAEP
with open(f"private.key", "rb") as f:
private_key = serialization.load_pem_private_key(
f.read(),
password=None,
backend=default_backend(),
)
secret_decrypted = private_key.decrypt(
secret_encrypted,
OAEP(
mgf=MGF1(algorithm=SHA1(), ),
algorithm=SHA1(),
label=None,
)
)
Found the solution at https://github.com/python-telegram-bot/python-telegram-bot/commit/a09394b218d3ae05dc1a1f74e782c701283fb82b#diff-eaefd62d25b87433b035868713d3437aR39.
Still would appreciate if someone would have explained me my mistake.

Can't use a data obj with timeit.Time module in python

I'm trying to measure how long it takes read then encrypt some data (independently). But I can't seem to access the a pre-created data obj within timeit (as it runs in its own virtual environment)
This works fine (timing file read operation):
t = timeit.Timer("""
openFile = open('mytestfile.bmp', "rb")
fileData = openFile.readlines()
openFile.close()""")
readResult = t.repeat(1,1)
print ("\Finished reading in file")
The the below doesn't work because I can't access 'fileData' obj. I can't create it again from inside the timeit function, otherwise it will increase the overall execution time.
timing encrypt operation:
tt = timeit.Timer("""
from Crypto.Cipher import AES
import os
newFile = []
key = os.urandom(32)
cipher = AES.new(key, AES.MODE_CFB)
for lines in fileData:
newFile = cipher.encrypt(lines)""")
encryptResult = tt.repeat(1,1)
timeit takes a setup argument that only runs once
from the docs:
setup: statement to be executed once
initially (default 'pass')
for example:
setup = """
from Crypto.Cipher import AES
import os
newFile = []
fileData = open('filename').read()
"""
stmt = """
key = os.urandom(32)
cipher = AES.new(key, AES.MODE_CFB)
for lines in fileData:
newFile = cipher.encrypt(lines)"""
tt = timeit.Timer(stmt, setup)
tt.repeat()
you can use the setup parameter of the timeit.Timer class like so:
tt = timeit.Timer("""
from Crypto.Cipher import AES
import os
newFile = []
key = os.urandom(32)
cipher = AES.new(key, AES.MODE_CFB)
for lines in fileData:
newFile = cipher.encrypt(lines)""",
setup = "fileData = open('mytestfile.bmp', 'rb').readlines()")
encryptResult = tt.repeat(1,1)
The setup code is only run once.

Categories