RSA: Sign / Verify - Examples in Python

Let's demonstrate in practice the RSA sign / verify algorithm. We shall use the pycryptodome package in Python to generate RSA keys. After the keys are generated, we shall compute RSA digital signatures and verify signatures by a simple modular exponentiation (by encrypting and decrypting the message hash).

Now, let's sign a message, using the RSA private key {n, d}. Calculate its hash and raise the hash to the power d modulo n (encrypt the hash by the private key). We shall use SHA-512 hash. It will fit in the current RSA key size (1024). In Python we have modular exponentiation as built in function pow(x, y, n):

Now, let's verify the signature, by decrypting the signature using the public key (raise the signature to power e modulo n) and comparing the obtained hash from the signature to the hash of the originally signed message:

Now, the signature will be invalid and the output from the above code will be:

Signature valid (tampered): False

Enjoy playing with the above RSA sign / verify examples. Try to modify the code, e.g. use 4096-bit keys, try to tamper the public key at the signature verification step or the signature.

The RSA Signature Standard PKCS#1

The simple use of RSA signatures is demonstrated above, but the industry usually follows the crypto standards. For the RSA signatures, the most adopted standard is "PKCS#1", which has several versions (1.5, 2.0, 2.1, 2.2), the latest described in RFC 8017. The PKCS#1 standard defines the RSA signing algorithm (RSASP1) and the RSA signature verification algorithm (RSAVP1), which are almost the same like the implemented in the previous section.

To demonstrate the PKCS#1 RSA digital signatures, we shall use the following code, based on the pycryptodome Python library, which implements RSA sign / verify, following the PKCS#1 v1.5 specification:

The output from the above code demonstrates that the PKCS#1 RSA signing with 1024-bit RSA private key produces 1024-bit digital signature and that it is successfully validated afterwards with the corresponding public key. If the message or the signature or the public key is tampered, the signature fails to validate. The output from the above example looks like this: