from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
new_file = open("md5_rehashed.txt", "w")
file_with_hashes = open('md5_hashed.txt', 'r')
key = RSA.importKey(open(received_message.decode('utf-8')).read())
cipher = PKCS1_OAEP.new(key)
for hash in file_with_hashes:
message = bytes(hash, 'utf-8')
ciphertext = cipher.encrypt(message)
new_file.write(ciphertext.hex().upper()+'\n')
file_with_hashes.close()
new_file.close()
Im using PKCS1_OAEP to encrypt strings stored in a local file,
next i convert the ciphertext to hex format and writing this str in a new .txt file.
In another file.py i need to read the new .txt file and decrypt all hashes of file, the problem is i can't find the form to comeback of ciphertext.hex() format to ciphertext format.
any suggestions?
here is my code of the second file.py
hashed_file = open(hashed_file_route, 'r')
unhashed_file = open('md5_unhashed', 'w')
key = RSA.importKey(open('private.pem').read())
cipher = PKCS1_OAEP.new(key)
for hash_line in hashed_file:
print(hash_line)
print(codecs.encode(bytes(hash_line,'utf-8'),'hex_codec'))
message = cipher.decrypt(hash_line.encode('utf-8'))
unhashed_file.write(message+ '\n')
unhashed_file.close()
hashed_file.close()
PS: sorry for my english
You should use bytes.fromhex(some_hex_string) to recover bytes from hexadecimal strings, as follows:
message = cipher.decrypt(bytes.fromhex(hash_line))
Related
I'm trying to encrypt and decrypt a file with PyCryptodome but without success. I can encrypt strings and data just fine but when trying to encrypt files it fails. I have 2 problems, first is that I can't encrypt larger strings. Witch i tried to solve by reading the file with a buffer. Second is that when I try to encrypt it as smaller buffers it just gives me an error "raise ValueError("Ciphertext with incorrect length.")"
My code looks like this:
from Crypto.Cipher import PKCS1_OAEP
import binascii
import ast
file_to_encrypt = "file_example_MP3_700KB.mp3"
buffer_size = 65536 # 64kb
input_file = open(file_to_encrypt, "rb")
output_file = open(file_to_encrypt + ".encrypted", "wb")
# Import keys
pub = open("publickey.txt", "rb")
pubKey = RSA.importKey(pub.read())
pub.close()
priv = open("privatekey.txt", "rb")
keyPair = RSA.importKey(priv.read())
priv.close()
# --------------------------------------------------------------
# Encrypt
encryptor = PKCS1_OAEP.new(pubKey)
buffer = input_file.read(buffer_size)
while len(buffer) > 0:
encrypted = encryptor.encrypt(buffer)
output_file.write(encrypted)
buffer = input_file.read(buffer_size)
input_file.close()
output_file.close()
# --------------------------------------------------------------
input_file = open(file_to_encrypt + ".encrypted", "rb")
output_file = open(file_to_encrypt + ".decrypted", "wb")
# Decrypt
decryptor = PKCS1_OAEP.new(keyPair)
buffer = input_file.read(buffer_size)
while len(buffer) > 0:
decrypted = decryptor.decrypt(ast.literal_eval(str(buffer)))
output_file.write(decrypted)
buffer = input_file.read(buffer_size)
input_file.close()
output_file.close()
# --------------------------------------------------------------
And generating the keys looks like this:
from Crypto.Cipher import PKCS1_OAEP
import binascii
import ast
# key generation
keyPair = RSA.generate(3072*2)
pubKey = keyPair.publickey()
# --------------------------------------------------------------
# Export keys
pub = open("publickey.txt", "wb")
pub.write(pubKey.exportKey('PEM'))
pub.close()
priv = open("privatekey.txt", "wb")
priv.write(keyPair.exportKey('PEM'))
priv.close()
# --------------------------------------------------------------
# Import keys
pub = open("publickey.txt", "rb")
pubKey = RSA.importKey(pub.read())
pub.close()
priv = open("privatekey.txt", "rb")
keyPair = RSA.importKey(priv.read())
priv.close()
# --------------------------------------------------------------
# encryption
msg = '550011'
encryptor = PKCS1_OAEP.new(pubKey)
encrypted = encryptor.encrypt(msg.encode())
# --------------------------------------------------------------
# decryption
decryptor = PKCS1_OAEP.new(keyPair)
decrypted = str(decryptor.decrypt(ast.literal_eval(str(encrypted))))[2:-1]
# --------------------------------------------------------------
print("Encrypted:", binascii.hexlify(encrypted))
print("Decrypted:", decrypted)
if msg == decrypted:
print("PASSED!")
else:
print("FAILED!")
Changing buffer_size fixes the first problem (that the data I'm trying to encrypt is too large.)
But I still can't decrypt my file after encrypting it.
Generating and importing keys works just fine. And encrypting and decrypting with them works just fine as well. As long as I'm only encrypting small strings and not files.
Programming language: Python
i have three files, one is to generate the key, 2nd is to encrypt, and the other is to decrypt.. the 1st and the 2nd files work.. but the decrypt file won't work
generate key file:
from cryptography.fernet import Fernet
def generate_key():
"""
Generates a key and save it into a file
"""
key = Fernet.generate_key()
with open("secret.key", "wb") as key_file:
key_file.write(key)
generate_key()
encrypt file -
from cryptography.fernet import Fernet
def load_key():
return open("secret.key", "rb").read()
def encrypt_message(message):
key = load_key()
encoded_message = message.encode()
f = Fernet(key)
encrypted_message = f.encrypt(encoded_message)
print(encrypted_message)
EncryptedTextWriteFile = open("encrypt.txt", "r+")
EncryptedTextWriteFile.write(str(encrypted_message))
notEncryptedFile = open("text.txt", "r")
notEncryptedText = notEncryptedFile.read()
if __name__ == "__main__":
encrypt_message(notEncryptedText)
notEncryptedFile.close()
Decrypt file -
from cryptography.fernet import Fernet
def load_key():
return open("secret.key", "rb").read()
def decrypt_message(encrypted_message):
key = load_key()
f = Fernet(key)
decrypted_message = f.decrypt(encrypted_message)
shit = decrypted_message.decode()
print(shit)
DencryptedTextWriteFile = open("decrypt.txt", "r+")
DencryptedTextWriteFile.write(shit)
EncryptedFile = open("decrypt.txt", "r")
EncryptedText = EncryptedFile.read()
if __name__ == "__main__":
decrypt_message(EncryptedText)
the string i tried - ( this test is in the text.txt )
hirusha
the error i get:
Traceback (most recent call last):
File "d:/development/Python/Everything/Releases/0.2/Build 02/_Releases/Encoder and Decoder/decrypt.py", line 27, in <module>
decrypt_message(EncryptedText)
File "d:/development/Python/Everything/Releases/0.2/Build 02/_Releases/Encoder and Decoder/decrypt.py", line 15, in decrypt_message
decrypted_message = f.decrypt(encrypted_message)
File "C:\Users\hirusha\AppData\Local\Programs\Python\Python38\lib\site-packages\cryptography\fernet.py", line 75, in decrypt
timestamp, data = Fernet._get_unverified_token_data(token)
File "C:\Users\hirusha\AppData\Local\Programs\Python\Python38\lib\site-packages\cryptography\fernet.py", line 100, in _get_unverified_token_data
utils._check_bytes("token", token)
File "C:\Users\hirusha\AppData\Local\Programs\Python\Python38\lib\site-packages\cryptography\utils.py", line 29, in _check_bytes
raise TypeError("{} must be bytes".format(name))
TypeError: token must be byte
The problem is that when you open the file decrypt.txt and read the file, it gets converted into string. But the .decrypt function only accepts input in byte.
I think this should solve your problem:
Generates a key and stores it in key.key file:
from cryptography.fernet import Fernet
def write_key():
"""
Generates a key and save it into a file
"""
key = Fernet.generate_key()
with open("key.key", "wb") as key_file:
key_file.write(key)
write_key()
Encrypts a file and stores it in enc_text.txt file:
from cryptography.fernet import Fernet
with open("key.key","rb") as f:
key=f.read()
f = Fernet(key)
with open('text.txt', 'rb') as original_file:
original = original_file.read()
encrypted = f.encrypt(original)
with open ('enc_text.txt', 'wb') as encrypted_file:
encrypted_file.write(encrypted)
Decrypts the enc_text.txt file and writes the output in decrypt.txt
from cryptography.fernet import Fernet
with open("key.key","rb") as f:
key=f.read()
f = Fernet(key)
with open('enc_text.txt', 'rb') as encrypted_file:
encrypted = encrypted_file.read()
decrypted = f.decrypt(encrypted)
with open('decrypt.txt', 'wb') as decrypted_file:
decrypted_file.write(decrypted)
Sujay's answer was posted while I was writing this one. It is correct, but I still wanted to post this to perhaps give some more insight into what this means.
Most (if not all) encryption tools work on bytes, not str. This is both because these days encrypting binary (non-string) data is more common, and because the encryption algorithms work on numbers, and bytes are strings of numbers in range(0, 256).
In the decryption program, you are loading the ciphertext in this line:
EncryptedFile = open("decrypt.txt", "r")
Contrast this to how you load the encryption key:
def load_key():
return open("secret.key", "rb").read()
The difference is the mode parameter to open: if there is a b in the string, it means it operates in binary mode, working on bytes rather than str. Here's an example:
>>> text = open('test.txt', 'r').read()
>>> text
'Hello World!\n'
>>> binary = open('test.txt', 'rb').read()
>>> binary
b'Hello World!\n'
>>> type(text)
<class 'str'>
>>> type(binary)
<class 'bytes'>
This distinction is important because str represents character sequences, and those can be encoded into binary in vastly different ways. Which of these you choose will affect what ones and zeros go into the encryption algorithm, and consequently what comes out.
The reason the encryption program worked, despite also reading the plaintext file in text mode, is because of this line:
encoded_message = message.encode()
str.encode converts the string into bytes using the encoding supplied, or the default one (usually UTF-8) if it is not specified. The bytes.decode method, seen in the decryption program, does the opposite: it converts bytes to str.
>>> text = '稲妻の腕を借らん草枕'
>>> text.encode()
b'\xe7\xa8\xb2\xe5\xa6\xbb\xe3\x81\xae\xe8\x85\x95\xe3\x82\x92\xe5\x80\x9f\xe3\x82\x89\xe3\x82\x93\xe8\x8d\x89\xe6\x9e\x95'
>>> text.encode('utf-16')
b'\xff\xfe2z\xbbYn0U\x81\x920\x1fP\x890\x930I\x83\x95g'
>>> u16_data = text.encode('utf-16')
>>> u16_data.decode('utf-16')
'稲妻の腕を借らん草枕'
>>> u16_data.decode() # this is why specifying the encoding is important
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
I'm receiving a TypeError when trying to encrypt + decrypt a file using pycryptodome. I've looked around but can't find much relevant to pycryptodome regarding this. The error is:
Error Image
The code I'm using is:
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import binascii
print("Now executing RSA")
# generate the RSA keys and print them on the console (as hex numbers and in the PKCS#8 PEM ASN.1 format)
keyPair = RSA.generate(3072)
pubKey = keyPair.publickey()
print(f"Public key: (n={hex(pubKey.n)}, e={hex(pubKey.e)})")
pubKeyPEM = pubKey.exportKey()
print(pubKeyPEM.decode('ascii'))
print(f"Private key: (n={hex(pubKey.n)}, d={hex(keyPair.d)})")
privKeyPEM = keyPair.exportKey()
print(privKeyPEM.decode('ascii'))
# encrypt the message using RSA-OAEP encryption scheme (RSA with PKCS#1 OAEP padding) with the RSA public key
# msg = b'A message for encryption'
f = open("plaintext.txt", "r")
f = f.read()
encryptor = PKCS1_OAEP.new(pubKey)
encrypted = encryptor.encrypt(f)
print("Encrypted:", binascii.hexlify(encrypted))
# decrypt the message using RSA-OAEP with the RSA Private key
decryptor = PKCS1_OAEP.new(keyPair)
decrypted = decryptor.decrypt(encrypted)
print('Decrypted:', decrypted)
You need to convert plaintext into bytes or read file as binary data. add b to read file as binary data.
f = open("plaintext.txt", "rb")
A side note You should consider closing the file after finishing using it
file = open("plaintext.txt", "rb")
f = file.read()
encryptor = PKCS1_OAEP.new(pubKey)
encrypted = encryptor.encrypt(f)
print("Encrypted:", binascii.hexlify(encrypted))
file.close()
Make sure both data types are equal. You can try converting the text file to bytes so the data types are equal, and hence can be concatenated.
I am trying to encrypt/decrypt with pycrypto in python. for the most part things have worked smooth but I am getting an odd problem when decrypting data.I have tried to encrypt/decrypt some jpgs for testing and although they encrypt/decrypt without issue, the decrypted files cannot be opened/are corrupted. To try to find the problem I saved a textfile with a random sentence similar to "test this file for integrity blah blah blah" and it decrypts correctly only after ".... integrity blah blah blah", everything before integrity is still in garbled characters. I'm not that knowledgable on AES, but im assuming that this is an encoding/decoding or padding error.
Here is my code:
#encryption
iv = Random.new().read( AES.block_size)
filePath = input("Path to file for encryption: ")
selFile = open(filePath, 'rb')
getBytes = bytes(selFile.read())
encPW = input("Enter password: ")
hashpw = hashlib.sha256(encPW.encode('UTF-8').digest())
destination = input("Destination path for encrypted file: ")
aes = AES.new(hashpw, AES.Mode_CFB, iv)
encFile = base65.b64encode(aes.encrypt(getBytes))
writetofile = open(destination, 'wb')
writetofile.write(encFile)
writetofile.close()
print("Encryption successful")
#Decryption
iv = Random.new().read( AES.block_size)
filePath = input("Path to file for decryption: ")
selFile = open(filePath, 'rb')
getBytes = bytes(selFile.read())
decPW = input("Enter password: ")
hashdecpw = hashlib.sha256(encPW.encode('UTF-8').digest())
destination = input("Destination path for decrypted file: ")
aes = AES.new(hashdecpw, AES.Mode_CFB, iv)
decFile = aes.decrypt(getBytes)
writetofile = open(destination, 'wb')
writetofile.write(decFile)
writetofile.close()
print("Decryption successful")
Any ideas on what could be causing the loss of the first characters, and preventing me from encrypting/decrypting files correctly?
You have at least three issues:
You probably mean hashlib.sha256(encPW.encode('UTF-8')).digest() instead of hashlib.sha256(encPW.encode('UTF-8').digest()) (the closing brace is at the wrong position)
You're encoding the ciphertext with Base64 before writing it to a file. You've forgot to decode it after reading it back from the file before decrypting it. For example:
getBytes = base64.b64decode(bytes(selFile.read()))
This is the big one: You need the exact same IV during the decryption that you've used for encryption. The IV is not secret, but it needs to be unique for every encryption that you've done with the same key. Commonly the IV is written in front of the ciphertext and read back for decryption.
#encryption
encFile = base64.b64encode(iv + aes.encrypt(getBytes))
#decryption
getBytes = base64.b64decode(bytes(selFile.read()))
iv = getBytes[:16]
aes = AES.new(hashdecpw, AES.Mode_CFB, iv)
decFile = aes.decrypt(getBytes[16:])
You're generating a new IV for encryption and decryption seperately, which comes to yield such problems. Here's what I recommend doing:
def encrypt(inpath, outpath, password):
iv = Random.new().read(AES.block_size)
with open(inpath, "rb") as f:
contents = f.read()
# A context manager automatically calls f.close()
key = pbkdf2.crypt(password, "")
# See notes
aes = AES.new(key, AES.Mode_CFB, iv)
encrypted = aes.encrypt(contents)
with open(outpath, "wb") as f:
f.write(iv + b":")
f.write(encrypted)
print("Encryption successful")
def decrypt(inpath, outpath, password):
with open(inpath, "rb") as f:
contents = f.read()
iv, encrypted = contents.split(b":")
key = pbkdf2.crypt(password, "")
aes = AES.new(key, AES.Mode_CFB, iv)
decrypted = aes.decrypt(contents)
with open(outpath, "wb") as f:
f.write(decrypted)
print("Decryption successful")
Some notes:
An IV is not meant to be secret, so it can be randomly generated once and then written to a file to be used later for decryption (as shown in this example)
A hashing algorithm is not strong enough for deriving keys, which is why there are special tools called key derivation algorithms (like PBKDF2 in python). Use those instead!
I have not tested this code myself, so it may not work properly.
I'm trying to encrypt the data in a file using AES encryption and then encrypt the AES key using RSA. But when i try to read the keys from the file it crops up with the error "RSA binascii.Error: Incorrect padding".
Traceback (most recent call last):
File "C:/Users/dbane_000/PycharmProjects/RSE/RSA.py", line 33, in <module>
key=RSA.importKey(f.read())
File "C:\Python27\lib\site-packages\Crypto\PublicKey\RSA.py", line 660, in importKey
der = binascii.a2b_base64(b('').join(lines[1:-1]))
binascii.Error: Incorrect padding
The error doesn't come always but maybe once for every five times that I run this code. What could be the reason?
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto import Random
import rsa
import base64
import os
BLOCK_SIZE = 32
PADDING = '{'
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
random_generator = Random.new().read
rsakey = RSA.generate(1024, random_generator)
f=open('key.pem','w')
cipher = PKCS1_OAEP.new(rsakey.publickey())
f.write(rsakey.exportKey("PEM"))
f.write(rsakey.publickey().exportKey("PEM"))
f.close()
f=open('key.pem','r')
key=RSA.importKey(f.read())
pubkey=key.publickey()
f.close()
secret = os.urandom(BLOCK_SIZE)
print secret
crypto =pubkey.encrypt(secret, 32)
secret =key.decrypt(crypto)
print crypto
print secret
cipher = AES.new(secret)
# encode a string
f=open('plaintext.txt','r')
plaintext=f.read()
f.close()
encoded = EncodeAES(cipher, plaintext)
print 'Encrypted string:', encoded
f=open('cipher_data.txt','w')
f.write(encoded)
f.close()
# decode the encoded string
decoded = DecodeAES(cipher, encoded)
print 'Decrypted string:', decoded
f=open('plaintext.txt','r')
plaintext=f.read()
f.close()
f=open('decrypted.txt','w')
f.write(decoded)
f.close()
Please try to check the contents of the input files from where you are taking key or data to encrypt or decrypt. This type of error would may occur,if the data from f.read() is in a desired format to perform decrypt.. And please try to write those keys or data at begining or desired index and fetch from that index..
# please check at this statements
f=open('key.pem','w')
cipher = PKCS1_OAEP.new(rsakey.publickey())
f.write(rsakey.exportKey("PEM"))
f.write(rsakey.publickey().exportKey("PEM"))
f.close()
f=open('key.pem','r')
key=RSA.importKey(f.read())
pubkey=key.publickey()
f.close()
I hope this may help you..