Signing has two steps. First a hash function compresses the message into a fixed-length fingerprint — the ring of spheres above the message. Changing even one character reshuffles every byte of that fingerprint (the "avalanche effect"), so no two different messages plausibly hash to the same fingerprint.
Second, the signer encrypts that fingerprint with their private key, producing the signature ring below it — this is the part only the signer can produce, because only they hold the private key.
To verify, anyone can recompute the hash of the message they received and decrypt the signature with the signer's public key. If the two fingerprints match, the message is authentic and untouched; if they differ, either the message was altered after signing or the signature wasn't produced with the matching private key.
signature = Encrypt(Hash(message), privateKey)
valid = Decrypt(signature, publicKey) == Hash(receivedMessage)
- Sign message — hashes the current text and encrypts that hash with the (simulated) private key, producing the signature ring.
- Verify signature — recomputes the hash of whatever text is in the box right now and compares it against the signature decrypted with the public key.
- Tamper message — flips one character in the message after it was signed, simulating an attacker modifying data in transit. The signature itself cannot change, so verification then fails.