Can use openssl instead of Python RSA and Base64 algorithms? - python

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.

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)

RSA decrypt returns extra data

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

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.

Why can't I use two DES keys that differ only in parity with OpenSSL?

When I perform following action in terminal I get different decryption text compared to message showing that these keys map to unique cipher
openssl enc -des-ecb -in text.in -out cipher.txt -k '96508092'
openssl enc -d -des-ecb -in cipher.txt -out text.in -k '82514145'
But when I implement it in programming using <openssl/des.h>, Crypto.cipher, pyDes I got same decrypted text. I found why I get same text and it is because these 8 byte keys map to a unique 7 byte key 0x3832343134313401. Refer to my previous question Why can I encrypt data with one DES key and successfully decrypt with another?
My question is: how is it implemented on OpenSSL terminal commands differently compared to mentioned libraries that it could map these 8 byte keys to unique cipher?
You need to use an uppercase -K if you want to supply key bytes. Otherwise, OpenSSL assumes its a password and derives a (different) key from it.
You also need to use the hex versions of the keys:
openssl enc -des-ecb -in text.in -out cipher.txt -K '3832353134313435'
openssl enc -d -des-ecb -in cipher.txt -out text.out -K '3933353035303434'

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.

Categories