i have this code that suppose to decode base64 encoded RSA text (by its key) but it doesn't work.
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import binascii
import base64
f = open('mykey.pem','r')
keyPair = RSA.import_key(f.read())
encoded = b'base64_encoded_text'
encrypted = base64.decodebytes(encoded)
decryptor = PKCS1_OAEP.new(keyPair)
decrypted = decryptor.decrypt(encrypted)
print('Decrypted:', decrypted)
The error is: "Incorrect decryption".
Does somebody know what could be the problem?
Related
I am trying to get rid of the openssl call below and replace it with pure python code.
import os
iv = "7bde5a0f3f39fd658efc45de143cbc94"
password = "3e83b13d99bf0de6c6bde5ac5ca4ae68"
msg = "this is a message"
out = os.popen(f'printf "{msg}" | openssl aes-128-cbc -base64 -K {password} -iv {iv}').read()
print(f"IV: {iv}")
print(f"PWD: {password}")
print(f"MSG: {msg}")
print(f"OUT: {out}")
yields:
IV: 7bde5a0f3f39fd658efc45de143cbc94
PWD: 3e83b13d99bf0de6c6bde5ac5ca4ae68
MSG: this is a message
OUT: ukMTwxkz19qVPiwU8xa/YM9ENqklbZtB86AaVPULHLE=
Between the 3 different libraries that people seem to suggest and various other code excerpts that don't seem to work anymore, I haven't been able to replicate it in pure python reliably. Would anyone have a working code example for the above?
With Python3 you can use PyCryptodome, binascii and base64.
from base64 import b64encode, b64decode
from binascii import unhexlify
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
iv = "7bde5a0f3f39fd658efc45de143cbc94"
password = "3e83b13d99bf0de6c6bde5ac5ca4ae68"
msg = "this is a message"
print(f"IV: {iv}")
print(f"PWD: {password}")
print(f"MSG: {msg}")
# Convert Hex String to Binary
iv = unhexlify(iv)
password = unhexlify(password)
# Pad to AES Block Size
msg = pad(msg.encode(), AES.block_size)
# Encipher Text
cipher = AES.new(password, AES.MODE_CBC, iv)
cipher_text = cipher.encrypt(msg)
# Encode Cipher_text as Base 64 and decode to String
out = b64encode(cipher_text).decode('utf-8')
print(f"OUT: {out}")
# Decipher cipher text
decipher = AES.new(password, AES.MODE_CBC, iv)
# UnPad Based on AES Block Size
plaintext = unpad(decipher.decrypt(b64decode(out)), AES.block_size).decode('utf-8')
print(f'PT: {plaintext}')
You can see more:
AES-128 CBC decryption in Python
Python Encrypting with PyCrypto AES
I need to decrypt an FTP password encrypted by pycrypto in AES CTR mode ,and for some reason I have to use cryptography instead,so how to do the decryption?
I want to know what is the nonce of cryptography should be?
this is the encrypt code by pycrypto
from Crypto.Util import Counter
from Crypto.Cipher import AES
def encrypt(text):
ctr = Counter.new(128, initial_value=1)
encrypto = AES.new(key, AES.MODE_CTR, counter=ctr)
encrypted = encrypto.encrypt(text)
return base64.b64encode(encrypted)
and the decrypt code by cryptography
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
def decrypt(text)
cipher = Cipher(algorithms.AES(key), None, backend=default_backend())
nonce = ?
cipher.mode = modes.CTR(nonce)
decryptor = cipher.decryptor()
decrypted = decryptor.update(encrypted.decode("base64"))
return decrypted
I'm trying to create a signature in node using this code:
var crypto = require('crypto');
var data = 'some data'
var signer = crypto.createSign('RSA-SHA256');
signer.write(data, 'base64');
signer.end();
var signature = signer.sign(privateKey, 'base64');
The signature and data are sent to python server.
Now I'm want to verify it using python code:
from base64 import b64decode, b64encode
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
rsakey = RSA.importKey(public_key)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
digest.update(data)
signer.verify(digest, b64decode(signature))
The verification fails.
When I use the same language for both sign and verify it works.
Any thoughts?
I had the same problem, and have found this to work:
import rsa
rsa.verify(message, signature, public_key)
As far as I understand, I should be able to use RSA to ensure authenticity or privacy, as I wish. In my case, I want to ensure authenticity so I encrypt the data with the private key and allow anyone to decrypt it with the public key. The data is not really secret but I need to guarantee that it was created by the owner of the public (and private) key.
When I try to decrypt using PyCrypto I get No private key error from PyCrypto. The code is this:
def _decrypt_rsa(decrypt_key_file, cipher_text):
from Crypto.PublicKey import RSA
from base64 import b64decode
key = open(decrypt_key_file, "r").read()
rsakey = RSA.importKey(key)
raw_cipher_data = b64decode(cipher_text)
decrypted = rsakey.decrypt(raw_cipher_data)
return decrypted
I'm calling it with the path to the public key file (in OpenSSH format.) The encrypted data isn't generated by me and it was not done with Python but PHP. In PHP there's a openssl_public_decrypt function that decrypts this data easily.
Is it possible at all to decrypt using the public key with PyCrypto?
That is totally insecure, because you are using raw RSA without padding.
Your application needs a signature, so you should not be dealing with encryptions and decryptions. For instance, PKCS#1 v1.5 is a good protocol, even though the signature is a piece of data that must be appended to what you want to prove the authenticity of.
To verify a PKCS#1 v1.5 signature in Python, you do:
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA
rsa_key = RSA.importKey(open(verification_key_file, "rb").read())
verifier = PKCS1_v1_5.new(rsa_key)
h = SHA.new(data_to_verify)
if verifier.verify(h, signature_received_with_the_data):
print "OK"
else:
print "Invalid"
I would strongly recommend to change the PHP code so that it creates such a signature.
Your function is correct. You just need to be giving it the path to your private key in order to decrypt instead of your public key. The public key is for encrypting, the private key is for decrypting.
def _decrypt_rsa(decrypt_key_file, cipher_text):
'''
Decrypt RSA encrypted package with private key
:param decrypt_key_file: Private key
:param cipher_text: Base64 encoded string to decrypt
:return: String decrypted
'''
from Crypto.PublicKey import RSA
from base64 import b64decode
key = open(decrypt_key_file, "r").read()
rsakey = RSA.importKey(key)
#optionally could use OAEP
#from Crypto.Cipher import PKCS1_OAEP
#rsakey = PKCS1_OAEP.new(rsakey)
raw_cipher_data = b64decode(cipher_text)
decrypted = rsakey.decrypt(raw_cipher_data)
return decrypted
from Crypto.Signature import PKCS1_v1_5 as pk
from Crypto.PublicKey import RSA
privatekey=RSA.importKey(open('pkcs8_rsa_private_key.pem','r').read())
def sign(self,signdata):
h=SHA.new(signdata)
signer = pk.new(privatekey)
signn=signer.sign(h)
signn=base64.b64encode(signn)
return signn
Just like this, but my privatekey is a string not a file. How I do it?
And how can I make privatekey string to pkcs8 format?