RSA decrypt returns extra data - python

I can decrypt some data encrypted via openssl command line tool, but some 'extra' data is returned with the original data.
I've created a encrypted file like this:
$ echo this is it >file.txt
$ openssl rsautl -encrypt -pubin -inkey public.pem -in file.txt -out encrypted.txt
And I can access the original data with:
from Crypto.PublicKey import RSA
key = open('/tmp/.private.key').read()
rsakey = RSA.importKey(key, 'MyPassphrase')
data = open('/tmp/encrypted.txt', 'rb').read()
original = rsakey.decrypt(data)
But some extra data is returned and the output is something like this:
\x02h\x83\xcfx\x84,\xb1\xa6 [...] \xcf5\x9f\xbbG\xf1\x14\xd0\x8d\x1f\xfe\x9c4\xbb\x1aB\xfa\xc3b\xc2\xe0K\x85\xb5\x10y\xe1\x8e\x00this is this\n
Can I avoid to receive this raw data before the decrypted data?
Obs.: The keys were created with openssl tool
Tks.

You are getting PKCS#1 v1.5 padded plaintext back. You need to remove the PKCS#1 v1.5 padding first. Currently you are performing textbook (or "raw") RSA decryption, which is little more than modular exponentiation. Try a PKCS#1 v1.5 capable class instead, like this one

Related

Convert .key formatted private key into .pem format with python3

I am trying to convert .key formatted private key into .pem formatted key using python3. Before using python3 I was able to convert private key into .pem format by simply running openssl command as:
openssl rsa -in <private_key_file> -outform PEM -out <new_file>
I would like to know how people are using python3 to convert it private keys into .pem or other formats. So far I've tried running subprocess.run() command to execute openssl command from python. It would be nice to know if there is python way of converting into .pem format.
I also tried following using pycryptodrome library https://pycryptodome.readthedocs.io/en/latest/index.html as per this thread pyOpenSSL creating a pem file which creates in pem format but wasn't successful.
def convert_key_to_pem_format(key_file):
print("Converting to pem/rsa format")
pv_key_string = key_file.exportKey()
with open ("private.pem", "w") as prv_file:
print("{}".format(pv_key_string.decode()), file=prv_file)
This is my code. Any help would be appreciated.
From the Cryptodome library, you can use the import_key method, which supports the following formats for an RSA private key:
PKCS#1 RSAPrivateKey DER SEQUENCE (binary or PEM encoding)
PKCS#8_ PrivateKeyInfo or EncryptedPrivateKeyInfo DER SEQUENCE (binary or PEM encoding)
Here's how you could use it:
from Cryptodome.PublicKey import RSA
key = RSA.import_key(open('private.key', "rb").read(), passphrase="(passphrase in case you have one)")
pv_key_string = key.exportKey()
with open ("private.pem", "w") as prv_file:
print("{}".format(pv_key_string.decode()), file=prv_file)

Can use openssl instead of Python RSA and Base64 algorithms?

Can use the openssl command to implement equivalent functionality with Python RSA and Base64 algorithms?
For example, the RSA public key and the password to be encrypted are known. The Python algorithm is
ciphertext = base64.b64encode(PKCS1_v1_5.new(pubkey).encrypt(password.encode('utf-8')))
Suppose the password is 123456 and the public key is pubkey.pem. Is the following openssl command equivalent to the Python algorithm?
echo 123456 | openssl rsautl -encrypt -pubin -inkey pubkey.pem -out ciphertext.txt | openssl enc -e -base64 -in ciphertext.txt -out r.txt
The result of r.txt is equivalent to the ciphertext of the Python algorithm?
Yes, it should be, well, if and only if your password is "123456" of course.
The randomization that the PKCS#1 v1.5 padding performs will mean that the ciphertext is always different, of course.
To test: decrypt the ciphertext using the reverse operations and the private key in Python. For more certainty, decrypt using openssl as well.

AES-ECB encryption (Difference between Python Crypto.Cipher and openssl)

i have a problem with encryption using python and openssl.
i wrote this small python script:
#!/usr/bin/python
from Crypto.Cipher import AES
obj = AES.new('Thisisakey123456', AES.MODE_ECB)
message = "Sample text....."
ciphertext = obj.encrypt(message)
print ciphertext
When i run the script with this command:
$ ./enc.py | base64
i get E0lNh0wtSg9lxxKClBEITAo= as a result.
If i do the same (or obviously it's not the same ;) ) in openssl i get another result:
$ echo -n "Sample text....." | openssl aes-128-ecb -k "Thisisakey123456" -nosalt -nopad | base64
yvNTGC+gwUK38uyJXIk/sQ==
What i am doing wrong?? i would expect the same base64 encoded string.
btw: i know ecb is bad, but i just play around, so it's no problem... ;)
You can try this command:
echo -n "Sample text....." | openssl aes-128-ecb -K 546869736973616b6579313233343536 -nopad | openssl base64
this explicitly specifies the key in hexadecimals. With -k the following "key" is actually a password, which is converted through an OpenSSL Password Based Key Derivation Function (PBKDF) called EVP_BytesToKey (using one iteration of SHA-1).
The result is E0lNh0wtSg9lxxKClBEITA==. This is not identical to E0lNh0wtSg9lxxKClBEITAo= but that's because Python adds a single newline character \n to the ciphertext, resulting in one extra byte to encode.

How to encrypt a file with python but can be decrypted using the shell?

I need to encrypt a file, send it to another person, who then can only decrypt it using shell.
I usually encrypt the file with the openssl command: openssl enc -aes-256-cbc -salt -in [filename] -out [file out name] -pass file:[direct path to key file], then send the file.
The other person then would decrypt the file again with the openssl command: openssl enc -d -aes-256-cbc -in [encrypted file] -out [file out name] -pass file:[direct path to key file]
I would use os.system to do this, but I feel like there has to be another way to encrypt the file with python which then could be decrypted on the shell side.
Do you need to use openssl?
I use command line GnuPG and there is very nice Python library: python-gnupg . It is a wrapper over command line gpg so they work simply the same.
Instead of key file (I think it contains password) you can use asymmetric cryptography. Create private/public pairs of keys for each part and then encrypt message using recipient public key and sigg it using sender private key. Recipient will check signature of sender using sender public key and recipient will decrypt message using her private key. Private keys can be protected by password but if you are sure your environments are safe you can use empty passwords.

Python RSA Decryption Using OpenSSL Generated Keys

Does anyone know the simplest way to import an OpenSSL RSA private/public key (using a passphrase) with a Python library and use it to decrypt a message.
I've taken a look at ezPyCrypto, but can't seem to get it to recognise an OpenSSL RSA key, I've tried importing a key with importKey as follows:
key.importKey(myKey, passphrase='PASSPHRASE')
myKey in my case is an OpenSSL RSA public/private keypair represented as a string.
This balks with:
unbound method importKey() must be called with key instance as first
argument (got str instance instead)
The API doc says:
importKey(self, keystring, **kwds)
Can somebody suggest how I read a key in using ezPyCrypto? I've also tried:
key(key, passphrase='PASSPHRASE')
but this balks with:
ezPyCrypto.CryptoKeyError: Attempted
to import invalid key, or passphrase
is bad
Link to docs here:
http://www.freenet.org.nz/ezPyCrypto/detail/index.html
EDIT: Just an update on this. Successfully imported an RSA key, but had real problem decrypting because eqPyCrypto doesn't support the AES block cipher. Just so that people know. I successfully managed to do what I wanted using ncrypt (http://tachyon.in/ncrypt/). I had some compilation issues with M2Crypto because of SWIG and OpenSSL compilation problems, despite having versions installed that exceeded the minimum requirements. It would seem that the Python encryption/decryption frameworks are a bit of a minefield at the moment. Ho hum, thanks for your help.
The first error is telling you that importKey needs to be called on an instance of key.
k = key()
k.importKey(myKey, passphrase='PASSPHRASE')
However, the documentation seems to suggest that this is a better way of doing what you want:
k = key(keyobj=myKey, passphrase='PASSPHRASE')
It is not clear what are you trying to achieve, but you could give M2Crypto a try. From my point of view it is the best OpenSSL wrapper available for Python.
Here is a sample RSA encryption/decription code:
import M2Crypto as m2c
import textwrap
key = m2c.RSA.load_key('key.pem', lambda prompt: 'mypassword')
# encrypt something:
data = 'testing 123'
encrypted = key.public_encrypt(data, m2c.RSA.pkcs1_padding)
print "Encrypted data:"
print "\n".join(textwrap.wrap(' '.join(['%02x' % ord(b) for b in encrypted ])))
# and now decrypt it:
decrypted = key.private_decrypt(encrypted, m2c.RSA.pkcs1_padding)
print "Decrypted data:"
print decrypted
print data == decrypted

Categories