Python 3.5, pycrypto 2.7a1, Windows, RC2 ciphering
Example:
print('Введите текс, который хотите зашифровать:')
text = input()
with open('plaintext.txt', 'w') as f:
f.write(text)
key = os.urandom(32)
with open('rc2key.bin', 'wb') as keyfile:
keyfile.write(key)
iv = Random.new().read(ARC2.block_size)
cipher = ARC2.new(key, ARC2.MODE_CFB, iv)
ciphertext = iv + cipher.encrypt(bytes(text, "utf-8"))
with open('iv.bin', 'wb') as f:
f.write(iv)
with open('ciphertext.bin', 'wb') as f:
f.write(ciphertext)
print(ciphertext.decode("cp1251"))
And I'd like to know how can I decrypt this text, I tried, but couldn't do it.
My try to decrypt:
os.system('cls')
print('Дешифруем значит')
with open('ciphertext.bin', 'rb') as f:
ciphertext = f.read()
with open('rc2key.bin', 'rb') as f:
key = f.read()
with open('iv.bin', 'rb') as f:
iv = f.read()
ciphertext = ciphertext.decode('cp1251')
iv = iv.decode('cp1251')
text = ciphertext.replace(iv, '')
text = cipher.decrypt(text)
with open('plaintext.txt', 'w') as f:
f.write(text)
print(text.decode("ascii"))
But I understood that I need cipher variable, and I can't save it to .txt or .bin file, so that why I'm asking for help.
The IV is a non-secret value and is commonly written in front of the ciphertext. Since, you've done that already, you don't need to write an additional IV file. RC2 has a block size of 64 bit, so the IV will always be 8 byte long.
with open('ciphertext.bin', 'rb') as f:
ciphertext = f.read()
with open('rc2key.bin', 'rb') as f:
key = f.read()
iv = ciphertext[:ARC2.block_size]
ciphertext = ciphertext[ARC2.block_size:]
cipher = ARC2.new(key, ARC2.MODE_CFB, iv)
text = cipher.decrypt(ciphertext).decode("utf-8")
with open('plaintext.txt', 'w') as f:
f.write(text)
print(text)
Other problems:
Don't simply decode binary data such as ciphertexts, keys or IV, because those are most likely not printable.
Don't re-use the same cipher object if you're doing something different. The decryption needs a freshly initialized ARC2 object.
Related
Good day,
I am doing an assignment for cryptography. It's an easy task I need to take any image, turn it into HEX, encrypt it and then decrypt it.
As I am working in Python and there was no specific encryption method in the task I just use Fernet.
I have an encryptor and decryptor scripts.
Encryption seems to be working because as a test I create a txt document with original HEX and after decryption the program states that original HEX and decrypted one are the same, however the decrypted image is not loading.
Could anyone help out a newbie?
Encryptor:
import binascii
from cryptography.fernet import Fernet
img = 'panda.png'
with open(img, 'rb') as f:
content = f.read()
hexValue = binascii.hexlify(content)
key = Fernet.generate_key()
with open('info/key.txt', mode='w+') as keyValue:
keyValue.write(key)
keyValue.seek(0)
f = Fernet(key)
encHexVal = f.encrypt(hexValue)
with open('info/encryptedHex.txt', mode='w+') as hexValueFile:
hexValueFile.write(encHexVal)
hexValueFile.seek(0)
a = f.decrypt(encHexVal)
with open('info/realValue.txt', mode='w+') as writeHex:
originalHex = writeHex.write(hexValue)
with open('info/realValue.txt', mode='r') as reading:
realValue = reading.read()
if realValue == a:
print("We're good to go!")
else:
print("Oops something went wrong. Check the source code.")
Decryptor:
import binascii
from cryptography.fernet import Fernet
with open('info/key.txt', mode='rb') as keyValue:
key = keyValue.read()
f = Fernet(key)
with open('info/encryptedHex.txt', mode='rb') as imageHexValue:
hexValue = imageHexValue.read()
a = f.decrypt(hexValue)
with open('info/realValue.txt', mode='r') as compare:
realContents = compare.read()
print("Small test in safe environment...")
if realContents == a:
print("All good!")
else:
print("Something is wrong...")
data = a.encode()
data = data.strip()
data = data.replace(' ', '')
data = data.replace('\n', '')
with open('newImage.png', 'wb') as file:
file.write(data)
I am using a random image from the internet of Po from Kung Fu Panda:
The principle problem is that although you hexlify then encrypt in the encryptor you don't unhexlify after decrypting in the decryptor. Its far more common to do things the other way, encrypt then hexlify so that the encrypted binary can be stored in regular text files or sent via http.
You have several problems with trying to write bytes objects to files open in text. I fixed those along the way. But it does leave me puzzled why a file called 'info/encryptedHex.txt' would be binary.
Encryptor
import binascii
from cryptography.fernet import Fernet
# Generate keyfile
#
# TODO: Overwrites key file on each run, invalidating previous
# saves. You could do `if not os.path.exists('info/key.txt'):`
key = Fernet.generate_key()
with open('info/key.txt', mode='wb') as keyValue:
keyValue.write(key)
# Encrypt image
img = 'panda.png'
with open(img, 'rb') as f:
content = f.read()
hexValue = binascii.hexlify(content)
f = Fernet(key)
encHexVal = f.encrypt(hexValue)
with open('info/encryptedHex.txt', mode='wb') as hexValueFile:
hexValueFile.write(encHexVal)
# Verification checks
a = f.decrypt(encHexVal)
# hexed bytes is same encoding as 'ascii'
with open('info/realValue.txt', mode='wb') as writeHex:
originalHex = writeHex.write(hexValue)
with open('info/realValue.txt', mode='r', encoding='ascii') as reading:
realValue = reading.read()
if realValue == a.decode('ascii'):
print("We're good to go!")
else:
print("Oops something went wrong. Check the source code.")
Decryptor
import binascii
from cryptography.fernet import Fernet
# Generate keyfile
#
# TODO: Overwrites key file on each run, invalidating previous
# saves. You could do `if not os.path.exists('info/key.txt'):`
key = Fernet.generate_key()
with open('info/key.txt', mode='wb') as keyValue:
keyValue.write(key)
# Encrypt image
img = 'panda.png'
with open(img, 'rb') as f:
content = f.read()
hexValue = binascii.hexlify(content)
f = Fernet(key)
encHexVal = f.encrypt(hexValue)
with open('info/encryptedHex.txt', mode='wb') as hexValueFile:
hexValueFile.write(encHexVal)
# Verification checks
a = f.decrypt(encHexVal)
# hexed bytes is same encoding as 'ascii'
with open('info/realValue.txt', mode='wb') as writeHex:
originalHex = writeHex.write(hexValue)
with open('info/realValue.txt', mode='r', encoding='ascii') as reading:
realValue = reading.read()
if realValue == a.decode('ascii'):
print("We're good to go!")
else:
print("Oops something went wrong. Check the source code.")
(base) td#timpad:~/dev/SO/Encrypting and decrypting in image$ cat de.py
import binascii
from cryptography.fernet import Fernet
with open('info/key.txt', mode='rb') as keyValue:
key = keyValue.read()
f = Fernet(key)
with open('info/encryptedHex.txt', mode='rb') as imageHexValue:
encHexValue = imageHexValue.read()
hexValue = f.decrypt(encHexValue)
binValue = binascii.unhexlify(hexValue)
with open('info/realValue.txt', mode='rb') as compare:
realContents = compare.read()
print("Small test in safe environment...")
if realContents == hexValue:
print("All good!")
else:
print("Something is wrong...")
with open('newImage.png', 'wb') as file:
file.write(binValue)
I have this error =>cryptography.fernet.InvalidToken, when I try to decrypt the content of my file at this line exit1 = key.decrypt(listCipher[0]).
I sought everywhere but I didn't found anything about this problem. I tried to replace the list by using ConfigParser but it still doesn't work and I don't think that is the problem. Some help is welcome.
from cryptography.fernet import Fernet
entry1 = "First_sentence"
entry2 = "Second_sentence"
entry3 = "Third_sentence"
##--- Key creation
firstKey = Fernet.generate_key()
file = open('.\\TEST\\key.key', 'wb')
file.write(firstKey)
file.close()
##--- Cipher entries
key = Fernet(firstKey)
chiffrentry1 = key.encrypt(bytes(entry1, "utf-8"))
chiffrentry2 = key.encrypt(bytes(entry2, "utf-8"))
chiffrentry3 = key.encrypt(bytes(entry3, "utf-8"))
listAll = [chiffrentry1, chiffrentry2, chiffrentry3]
##-- Write cipher text in file
with open('.\\TEST\\text_encrypt.txt', 'w') as pt:
for ligne in listAll:
pt.write("%s\n" % ligne)
##--- Recover file to decrypt cipher text
listCipher = []
with open('.\\TEST\\text_encrypt.txt', 'rb') as pt:
for line in pt:
listCipher.append(line.strip())
exit1 = key.decrypt(listCipher[0])
exit2 = key.decrypt(listCipher[1])
exit3 = key.decrypt(listCipher[2])
print(exit1)
print(exit2)
print(exit3)
The '%s\n'%ligne is modifying your data. For instance if I do the following:
>>> with open('afile.txt', 'w') as fh:
for i in range(2):
fh.write('%s\n'%b'hi there')
12
12
>>> with open('afile.txt', 'rb') as fh:
for line in fh:
print(line)
b"b'hi there'\n"
b"b'hi there'\n"
The issue here is the type conversions you are doing. Fernet's operations expect bytes and you are storing the encrypted values as strings. When you convert a bytes object to a string, you don't get exactly what that byte-string was. To avoid this, don't convert the types
with open('.\\TEST\\text_encrypt.txt', 'wb') as pt:
# join supports byte-strings
to_write = b'\n'.join(listAll)
pt.write(to_write)
# Now I can read a bytes object directly
with open('.\\TEST\\text_encrypt.txt', 'rb') as fh:
# this is a single bytes-string with b'\n' chars inside it
contents = fh.read()
# byte-strings also support split
ciphers = contents.split(b'\n')
for cipher in ciphers:
print(key.decrypt(cipher))
I create the key and I encrypt the message send by user, and store this message in a file and after i try to decrypt this message in the file, but i get this error cryptography.fernet.InvalidToken. I don't use the time for the token and I have also converted in byte after.
My code is:
from cryptography.fernet import Fernet
key = Fernet.generate_key()
f = Fernet(key)
def encry():
global f
what = input("What i need to encrypt?")
what_b = str.encode(what)
token = f.encrypt(what_b)
print("key generated")
print("encrypted")
file1=open("string.txt", "w")
file1.write(str(token))
file1.close()
file2=open("key.txt", "w")
file2.write(str(key))
file2.close()
def decry():
global f
print("decrypted")
file1=open("string.txt", "r").read()
file_de=str.encode(file1)
file2=open("de.txt", "w")
what_d = f.decrypt(file_de)
file1.close()
file2.write(str(what_d))
file2.close()
choose = input("Do you want, encrypt or decrypt?" + " " + "(e/d)")
if choose == "e":
encry()
elif choose == "d":
decry()
else:
print("Nothing to do")
The problem comes from the way you write and read the message and the key to and from the files. Indeed, the encrypted text and the keys are not strings, but byte strings and need to be treated in a different way.
In your case, when reading and writing it is enough to specify that you do it in binary mode and you can do it by adding the b flag. See the documentation for more detailed information.
Moreover, in your decrypt you also need to read the key from the file.
def encry():
key = Fernet.generate_key()
f = Fernet(key)
what = "example"
what_b = str.encode(what)
token = f.encrypt(what_b)
with open("string.txt", "wb") as f1, open("key.txt", "wb") as f2:
f1.write(token)
f2.write(key)
def decry():
with open("string.txt", "rb") as f1, open("key.txt", "rb") as f2:
token = f1.read()
key = f2.read()
f = Fernet(key)
what_d = str(f.decrypt(token),'utf-8') #converting back to string
encry()
decry()
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 and decrypt video using simplecrypt simplecrypt and everthing works perfectlly but the problem is after program decrypt the video Myvideo.mp4.enc to example-decrypt.mp4 the example-decrypt.mp4 not working "Corrupted file"
My code:
from simplecrypt import encrypt, decrypt
def encrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
plaintext = fo.read()
enc = encrypt(key, plaintext)
with open(file_name + ".enc", 'wb') as fo:
fo.write(enc)
def decrypt_file(file_name, dec_file, key):
with open(file_name, 'rb') as fo:
ciphertext = fo.read()
dec = decrypt(key, ciphertext)
with open(dec_file, 'wb') as fo:
fo.write(dec)
encrypt_file('Myvideo.mp4', 'xfxw3wxq233')
decrypt_file('Myvideo.mp4.enc', 'example-decrypt.mp4', 'xfxw3wxq233')
How i can fix this please.