Can't use a data obj with timeit.Time module in python - 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.

Related

Encrypting mulitple files with hybrid encryptions, encountering error when decrypting

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 :")

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.

Encrypt data in PostgreSQL and decrypt the data in Python

I have data in my database that I need to encrypt. I will then download the database to csv files. I have a python program that can decrypt the specific columns in a csv file. The problem is that I don't get my data out from the python program.
sql function:
CREATE OR REPLACE FUNCTION AESEncrypt (data TEXT,pass TEXT)
RETURNS TEXT AS $crypted$
declare
crypted TEXT;
key BYTEA;
iv BYTEA;
BEGIN
key := digest(convert_to(pass, 'utf-8'), 'sha256');
iv := digest(convert_to(CONCAT(data , 'salt'), 'utf-8'), 'md5');
crypted := encode(encrypt_iv(convert_to(data, 'utf-8'), key, iv, 'aes'), 'base64');
RETURN crypted;
END;
$crypted$ LANGUAGE plpgsql;
python program:
import csv
import time
import base64
from hashlib import sha256, md5
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
password = 'Password'
inputFile = 'test.txt'
outputFile = 'out.txt'
delimiter = ';'
columns = [0]
backend = default_backend()
key = sha256(password.encode('utf-8')).digest()
iv = md5((password + 'salt').encode('utf-8')).digest()
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
def encrypt(input):
input = bytes(input, 'utf-8')
#Padding
length = 16 - (len(input) % 16)
input += bytes([length])*length
#Encrypt
encryptor = cipher.encryptor()
return base64.b64encode(encryptor.update(input) + encryptor.finalize()).decode("utf-8")
def decrypt(input):
input = base64.b64decode(input)
decryptor = cipher.decryptor()
data = decryptor.update(input) + decryptor.finalize()
data = data[:-data[-1]] #Remove padding
print(data)
return data.decode('utf-8')
def main():
start_time = time.time()
with open(inputFile, 'r') as csvfileIn:
with open(outputFile, 'w', newline='') as csvfileOut:
spamreader = csv.reader(csvfileIn, delimiter=delimiter)
spamwriter = csv.writer(csvfileOut, delimiter=delimiter)
firstRow = True
for row in spamreader:
if not firstRow:
for pos in columns:
row[pos] = decrypt(row[pos])
firstRow = False
spamwriter.writerow(row)
print("--- %s seconds ---" % (time.time() - start_time))
main()
If I encrypt the file with the encrypt function written in the python program then I get the correct result if i would decrypt it.
If I would call the sql funcion as AESEncrypt('data', 'Password') then it returns the base64 string Ojq6RKg7NgDx8YFdLzfVhQ==
But after decryption I get the empty string as result and not the string data. If I look at the print statment before the utf-8 decode step in the decryption function it prints out the following on the console b'', so it looks like it could be something wrong with the padding. If I would print before I remove the padding I get b'\x85\x90sz\x0cQS\x9bs\xeefvA\xc63-'. If I will encrypt a long sentence then I will actually see parts of the text in the byte outputs above.
Do anyone know what I have done wrong?

Create byte array for zip file

I'm trying to import a zip file in to Confluence with the RPC importSpace object, but it keeps giving errors.. Atlassian has the following documentation that you can use for this:
public boolean importSpace(String token, byte[] importData)
I have created a small Pyhton script that loops through a file where the zip filenames are saved:
#!/usr/bin/python
import xmlrpclib
import time
import urllib
confluence2site = "https://confluence"
server = xmlrpclib.ServerProxy(confluence2site + '/rpc/xmlrpc')
username = ''
password = ''
token = server.confluence2.login(username, password)
loginString = "?os_username=" + username + "&os_password=" + password
filelist = ""
start = True
with open('exportedspaces.txt') as f:
for file in f:
try:
print file
f = open(os.curdir+ "\\zips\\" + file, 'rb')
fileHandle = f.read()
f.close()
server.confluence2.importSpace(token, xmlrpclib.Binary(fileHandle))
except:
print file + " failed to restore"
failureList.append(file)
Where does it goes wrong?

Hashing files with python

I'm writing a python script which should look for all the files with the same content in the cwd. My idea is to use hash functions, but when I run the script every file gets a different digest even though they are copies, which doesn't happen if I compute them on the terminal. I just can't figure out where the problem is. Here's the code
import sys
import os
import hashlib
from collections import defaultdict
blocksize = 65536
def hashfile(file, hasher):
buf = file.read(blocksize)
while len(buf)>0:
hasher.update(buf)
buf = file.read(blocksize)
#print hasher.hexdigest()
return hasher.hexdigest()
def main():
dir = os.getcwd()
files = os.listdir(dir)
dict = defaultdict(list)
l = []
hasher = hashlib.sha256()
for file in files:
hash = hashfile(open(file, 'rb'), hasher)
l.append((hash, file))
for k, v in l:
dict[k].append(v)
for k in dict.items():
print k
if __name__ == '__main__':
main()
You are using a single hasher for all files and it's be updating accumulatively. When you are dealing with the second file, you get a digest of the first and second file.
#hasher = hashlib.sha256()
for file in files:
hasher = hashlib.sha256()
hash = hashfile(open(file, 'rb'), hasher)
l.append((hash, file))
Move the hasher = hashlib.sha256() line to the for loop.
I think it's better to move hasher = hashlib.sha256() to the hashfile function:
def hashfile(file):
hasher = hashlib.sha256()
buf = file.read(blocksize)
#original code here
It will make the code more clear.

Categories