Skip to content
Advertisement

Sign a byte string with SHA256 in Python

Currently I have some code that signs a byte string with the SHA256 algorithm using the native OpenSSL binary, the code calls an external process, sends the parameters, and receive the result back into the Python code.

The current code is as follows:

JavaScript

When original_string is too big, I might have problems with the result (from the communication with an external process I think), that’s why I’m trying to change it to a Python only solution:

JavaScript

This result in a completely different string than the first one.

What would be the way to implement the original code without calling an external process?

Advertisement

Answer

The openssl command you used does three things:

  • Create a hash of the data, using SHA256
  • If RSA is used, pad out the message to a specific length, using PKCS#1 1.5
  • Sign the (padded) hash, using the private key you provided. It’ll depend on the type of key what algorithm was used.

The hmac module does not serve the same function.

You’ll need to install a cryptography package like cryptography to replicate what openssl dgst -sign does. cryptography uses OpenSSL as a backend, so it will produce the same output.

You can then

  • load the key with the load_pem_private_key() function. This returns the right type of object for the algorithm used.
  • use the key to sign the message; each key type has a sign() method, and this method will take care of hashing the message for you if you so wish. See for example the Signing section for RSA.

    However, you’ll need to provide different kinds of config for the different .sign() methods. Only the RSA, DSA and Elliptic Curve keys can be used to create a signed digest.

You’ll have to switch between the types to get the signature right:

JavaScript

If you need to hash a large amount of data, you can hash the data yourself first, in chunks, before passing in just the digest and the special util.Prehashed() object:

JavaScript

This uses the iter() function to read data from a binary file in chunks of 64 kilobytes.

Demo; I’m using an RSA key I generated in /tmp/test_rsa.pem. Using the command-line to produce a signed digest for Hello world!:

JavaScript

or using the Python code:

JavaScript

Although the line lengths differ, the base64 data the two output is clearly the same.

Or, using a generated file with random binary data, size 32kb:

JavaScript

Processing the same file in Python:

JavaScript
Advertisement