Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to encrypt data with RSA private key (not normal signing) in Python?

I want to make RSA encryption with private key (not normal signing), but PyCryptodome seems not be able to do it.

The reason I need to do it with private key is, I need to get the same results as from a Java program not written by me, which wrongly uses javax.crypto.Cipher and private key to sign messages...

import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import javax.crypto.Cipher;

...

String deviceKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASC...";
PKCS8EncodedKeySpec localPKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decode(deviceKey).getBytes("UTF-8"));
PrivateKey localPrivateKey = KeyFactory.getInstance("RSA").generatePrivate(localPKCS8EncodedKeySpec);

byte[] hash = MessageDigest.getInstance("SHA-256").digest("test".getBytes());
Cipher localCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
localCipher.init(Cipher.ENCRYPT_MODE, localPrivateKey);
String sign = new String(Base64.encode(localCipher.doFinal(hash)));
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from Crypto.Hash import SHA256

...

deviceKey = 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASC...'
privateKey = RSA.importKey(deviceKey)
hash = SHA256.new('test'.encode()).digest()
signer = PKCS1_v1_5.new(privateKey)
sign = b64encode(signer.encrypt(hash))

Result of the Java program:

  • Hash: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

  • Sign: k8y6zMfl0KVuQWWOmRxieXF1aH0dpVUX......(always the same)

Result of my Python script:

  • Hash: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

  • Sign: GfLVqZDnu5aLHHbi0tM5OtCBEVKKRcjW......(it changes every time)

like image 522
zry98 Avatar asked Oct 28 '25 07:10

zry98


1 Answers

You don't use private keys to encrypt data.

  • A private key can sign data, which can be verified by the matching public key.
  • A public key can encrypt data, which can be decrypted by the matching private key.

If what you really want is to sign your hash, instead of using the encrypt function, you should use the sign function.

So, instead of

from Crypto.Cipher import PKCS1_v1_5
PKCS1_v1_5.new(privateKey).encrypt(hash)

you might want to try

from Crypto.Signature import pkcs1_15
pkcs1_15.new(privateKey).sign(hash)

I wrote a little blog post about signing/verifying using pycryptodome, if you want to take a look.

like image 165
epalm Avatar answered Oct 31 '25 11:10

epalm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!