Exercise: Sign and Validate Data

Let's put your new knowledge of cryptographic signatures to use by signing a message and validating it! This exercise will walk you through the process, allowing you to get more familiar with what is needed to create and validate a digital signature.

How exactly do you sign a message? What data is needed to validate the signature on that message? Let's write a simple script to sign and validate a message to find out!

As we've discussed, Bitcoin uses elliptic curve cryptography, or more specifically ECDSA, Elliptic Curve Digital Signature Algorithm. While the process here would be the same using a wide variety of curves, let's use what Bitcoin uses, the secp256k1 curve.

To do that we'll want to use a ECDSA library that supports secp256k1. The Pure-Python ECDSA library, found at https://pypi.org/project/ecdsa/ is what we'll use in the below example.

First well want to import from SigningKey, and SECP256k1 from ecdsa:

from ecdsa import SigningKey, SECP256k1


We can't sign or verify a message without some keys! Next let's generate a private key, which the ecdsa library calls a signing key, and a corresponding public key which is called a verifying key.

Note that here is where we are specifying which curve to use, Secp256k1.

sk = SigningKey.generate(curve=SECP256k1)


And our public, or verifying, key…

vk = sk.verifying_key


Next, we'll need a message to sign. In this script, you can use whatever string you'd like, but just for fun, we'll use a crypto classic here.

signature = sk.sign(b"Not your keys, not your coins!")


You may want to make good use of the print() function in your script just to see the data that is being produced at each step along the way. Note: most of the data will be in hexadecimal format, which we'll discuss more later.

Now we have all the components we need to validate the signature! We have…

  1. The signature
  2. The message
  3. The public or verifying key

Let's put these components together and see if we have produced a valid signature.

assert vk.verify(signature, b"Not your keys, not your coins!")


If the assertion is successful your script will continue on.

It's important to note that this function, vk.verify, is abstracting away quite a lot. What is going on behind the scenes is quite interesting. You may be asking, what exactly is a digital signature? It's two numbers which we call R and S. So the values being used here are really, R, S, the message, and the public key. The calculations done from there can verify that R and S were produced from a combination of the message and the private key associated with the public key being used as an input here. And there is still more to it than that which we'll be reading about shortly.

Let's test what we have done by trying to break it. If any one of these components is incorrect you will receive an error message. Test it out by changing one of these components. You can try changing the message slightly, or use a different public key, or try a different signature. If any one of these components doesn't' line up, the signature won't validate.

Below is an example of a complete script…

from ecdsa import SigningKey, SECP256k1
sk = SigningKey.generate(curve=SECP256k1)
print(sk)
 
vk = sk.verifying_key
print(vk)
 
signature = sk.sign(b"Not your keys, not your coins!")
print(signature)
 
assert vk.verify(signature, b"Not your keys, not your coins!")
 
print("If your script runs to this point without an error, congrats, you successfully validated the signature!")

Source: Saylor Academy
Creative Commons License This work is licensed under a Creative Commons Attribution 4.0 License.

Last modified: Monday, October 4, 2021, 5:33 PM