Anybody can type a name into a payment
A digital signature is a value that only the holder of a secret key can make, and that anybody can check with a public key. It shows who sent a message and that it was not changed.
A ledger needs this. Without it, anybody could add "Asha pays Ben 5" and put Asha's name on it.
By the end of this lesson
Note
I can explain how a signature shows who sent a payment and that it was not changed.
Key words
| Word | What it means |
|---|---|
| Private key | a secret that only its owner holds |
| Public key | a value anybody may see, made from the private key |
| Signature | a value made from a message and a private key |
| Verify | to check a signature using the public key |
| One-time signature | a key pair that is safe for only one message |
The cells students fill in are left blank in this preview.
A signature proves who made a message
Ownership here means one thing: holding a private key. Each account has a public key that everybody can see. It stands for the account.
To pay from that account, the owner signs the payment with the private key. Anybody can verify the signature with the public key. If it checks out, the payment came from the key's holder.
Sign a message and check it
docker exec jupyter python3 steps/sign.pyShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Read what the lab printed
The lab printed four lines. The public key holds 256 pairs of hashes, and the signature holds 256 revealed secrets. The signed message checks out as True.
Then one letter of the message changed, and the same signature checked out as False. A signature is tied to the exact message, so an edit to a payment breaks it.
A signature can be made from hashes alone
The lab uses a Lamport signature. The private key is 256 pairs of secrets. The public key is the hash of each secret.
To sign, hash the message and look at its 256 bits. For each bit, reveal one secret from its pair: the first if the bit is 0, the second if it is 1. That list of revealed secrets is the signature.
Worked example: signing four bits
| Position | Bit of the message | Pair of secrets | Revealed |
|---|---|---|---|
| 1 | 1 | a0, a1 | a1 |
| 2 | 0 | b0, b1 | b0 |
| 3 | 1 | c0, c1 | c1 |
| 4 | 1 | d0, d1 | d1 |
The cells students fill in are left blank in this preview.
Try it: sign four bits and verify
import hashlib
def h(text):
return hashlib.sha256(text.encode()).hexdigest()
# The private key: a pair of secrets for each of 4 bits.
secret = [["a0", "a1"], ["b0", "b1"], ["c0", "c1"], ["d0", "d1"]]
public = []
for pair in secret:
public.append([h(pair[0]), h(pair[1])])
bits = [1, 0, 1, 1]
signature = []
for i in range(4):
signature.append(secret[i][bits[i]])
print("signature:", signature)
# The checker only has the public key and the bits.
claimed = [1, 0, 1, 1]
ok = True
for i in range(4):
if h(signature[i]) != public[i][claimed[i]]:
ok = False
print("checks out:", ok)
# Change the last claimed bit to 0 and run again.
Verifying means hashing each revealed secret
The checker does not know the secrets. It knows the public key, which is the hash of every secret.
For each bit of the message, the checker hashes the revealed secret and compares it with the matching entry of the public key. All 256 must match. Nobody can find a secret from its hash, so only the key's owner could reveal it.
A common mistake
Warning
Many people think a signature hides the message. It does not. The message is sent in the open beside its signature. A signature shows who made the message and that it is unchanged. To hide a message you would encrypt it, which is a different job.
This key pair may sign only one message
Each signature reveals half of the secrets. A second message reveals other secrets, and now a cheat who has seen both can mix them to sign a third message that nobody signed.
So a Lamport key pair is used once and then thrown away. It is a good way to learn the idea, and it is not meant for real use.
List the functions in the signing file
docker exec jupyter grep -n def lamport.pyShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.