0

I'm working with a service that uses raw RSA with a private key to sign a payload. The data is effectively produced using:

openssl rsautl -inkey private_key.pem -raw -sign

(Also, the result of encrypting with the private key)

Unfortunately, in Pycrypto the corresponding .verify() method only takes an argument to verify the data against to return true or false.

In openssl, this could be achieved with one of the following:

# Private key based
openssl rsautl -inkey private_key.pem -raw -verify
# Public key based
openssl rsautl -inkey public_key.pem -pubin -raw -verify

How can I achieve the same functionality in Pycrypto?

(I understand the risks of raw RSA. A custom padding mechanism has been implemented to mitigate some of those risks. Unfortunately, it's not possible to change the current implementation)

Alastair McCormack
  • 26,573
  • 8
  • 77
  • 100
  • 1
    FWIW, it's possible to access the OpenSSL library directly in Python by using the `ctypes` module. However, you do need to negotiate the rabbit warren of the OpenSSL docs and header files. ;) [Here](https://gist.github.com/PM2Ring/ac1d31d7391c94410c142d5a059b4cda) is an example that shows how to do some simple AES tasks that way. – PM 2Ring Jan 16 '18 at 12:03
  • thanks @PM2Ring. I'm lucky that I could solve this with native code, but your example is a really neat example of ctypes, which I'm sure to use in the future – Alastair McCormack Jan 16 '18 at 13:51
  • In the title you have the word 'view'. Did you mean 'verify'? – President James K. Polk Jan 17 '18 at 14:08
  • Hi @JamesKPolk. The problem is that I essentially want to **see** the result of the decryption of the signature using the public key. The verify function of Pycrypto does not allow me to see the result, only check it against a known value. In some circumstances I don't have a know the value to check against or I simply want to see the result of a private key encryption. – Alastair McCormack Jan 17 '18 at 15:19

1 Answers1

0

Delving into the .verify() method, one can find how Pycrypto builds the verification signature before comparing it to the given required signature.

It essentially uses Python's pow() method with the key's public (e) and the key's modulus (n). You will first need to pack the secret message into a (long) integer and then convert the result back to bytes. Fortunately, Pycrypto provides everything you need.

from Crypto.PublicKey import RSA
from Crypto.Util import number

key = RSA.importKey(private_key_str, key_password_str)

# The message must be packed as a long first.
secret_message_long = number.bytes_to_long(secret_message_bytes)
# The magic!        
verify_long = pow(encrypted_session_key_long, key.e, key.n)
# and back to bytes
verify_bytes = number.long_to_bytes(result_long)

# Convert message back to a str (Unicode str in Py2).
# Replace 'utf-8' with the correct encoding for *your* message!!!!!
verify_str = verify_bytes.decode('utf-8')
Alastair McCormack
  • 26,573
  • 8
  • 77
  • 100