Skip to content
Blockchain Association of Cameroon
BAC-L0-FOUND-1053 h

Public keys, private keys, signatures

Asymmetric cryptography as a mechanism of authority: what a signature proves, who can produce one, and why the private key is the identity itself.

  • Generate a key pair and sign a message a third party can verify
  • Explain the difference between signing and encrypting
  • Describe what happens, irreversibly, when a private key leaks

On a network where nobody knows anybody, one question matters: who has the right to say "this transfer is authorised"? Asymmetric cryptography answers it with two mathematically linked keys: a private key you keep, and a public key you show to everyone. In this workshop you generate a key pair in your browser, sign a message, have it verified, then break the signature to see what it really protects. You will also learn what a signature does not prove, why signing is not encrypting, and why a leaked private key cannot be repaired.

Lessons 1/4 · 15 min

A key pair: a secret and its public counterpart

The starting question

You send 5,000 CFA francs by mobile money. The operator asks for your PIN and checks it is right: to do that, it must know the secret (or hold what is needed to check it). If someone at the operator is dishonest, your secret is at risk.

On an open network there is no trusted operator. You need a way to prove "it is really me" without ever handing the secret to the person who checks. That is the purpose of a key pair.

The concept

A key pair is two linked numbers:

  • the private key: a secret number drawn at random. It is 32 bytes (256 bits) for common elliptic curves such as P-256 or Ed25519;
  • the public key: computed from the private key by a one-way operation. You can publish it.

"One-way" means: going from private key to public key is fast; going back is, as far as current knowledge goes, infeasible for well-chosen keys. This is not an absolute mathematical proof: it is a hardness assumption (the elliptic-curve discrete logarithm) that experts have been testing for decades. A large enough quantum computer would break that assumption; none exists today, but it is a known limit.

How many private keys are possible?

A 256-bit private key can take about 2^256 ≈ 1.16 × 10^77 values. Two people drawing at random will not land on the same one, provided the randomness is of cryptographic quality. A weak generator (for example a browser's Math.random) makes the key guessable. Your browser uses the operating system's generator for this, not Math.random.

Two algorithm families in this workshop

ECDSA P-256Ed25519
Private key32 bytes32 bytes (seed)
Signature (raw form)64 bytes64 bytes
Used herebrowser toolindependent lab

The course catalogue names ed25519 for the local lab; the browser tool instead uses ECDSA on the P-256 curve because that is what the browser's cryptography API (WebCrypto) offers everywhere. The ideas are the same: a private key signs, a public key verifies. Bitcoin uses another curve (secp256k1); Ethereum too. The concepts transfer, the bytes do not.

Your turn

Open the tool below and generate a key pair. Note that the private key is never displayed: it stays in your browser's memory. Export the public key: it is base64 text you could send to anyone.

What this does NOT guarantee

Owning a key pair says nothing about who you are. Anyone can generate a thousand in a second. A public key is just a number; tying it to a person or a company takes something else (see the next lesson).

Recap

  • The private key is a large secret random number; the public key follows from it in one direction only.
  • That one-way property is a hardness assumption, not an absolute proof.
  • A key pair proves no identity by itself.

Interactive tool

ECDSA P-256 signature

Generate a key pair in your browser, sign a message, then verify the signature.

The private key is created with extractable: false: the browser keeps it in memory and never lets it be exported, and it is neither displayed nor stored. It lives only in this tab: reloading the page loses it.

Public key (SPKI, base64)

No key yet. Generate a pair to sign.

Signature (base64, P1363 format: r ‖ s, 64 bytes)

…

ECDSA with SHA-256 on the P-256 curve. WebCrypto returns r and s concatenated (32 + 32 bytes), not DER encoding.

Verify a signature

Lessons 2/4 · 20 min

Signing and verifying: what a signature proves

The starting question

Aminata receives a message: "Pay 5,000 CFA francs to Didier". A signature is attached. What exactly does she know if verification succeeds?

The concept

There are two operations:

  • sign(private_key, message) → a signature (64 bytes in raw form for ECDSA P-256 or Ed25519);
  • verify(public_key, message, signature) → true or false, nothing else.

In practice the signature covers the message's digest (see workshop 104): ECDSA signs a digest of the message (the page's tool uses SHA-256; ECDSA itself does not impose it), Ed25519 builds in its own hashing. That is why signing a 1 GB file is as fast as signing an SMS.

A worked example with the tool

In the tool, sign the text Pay 5000 CFA to Didier, then run five verifications:

Message verifiedSignaturePublic keyResult
Pay 5000 CFA to Didieryoursyourstrue
Pay 5001 CFA to Didieryoursyoursfalse (one character changed)
Pay 5000 CFA to Didieran altered signatureyoursfalse
Pay 5000 CFA to Didieryourspublic key of another pairfalse
Pay 5000 CFA to Didieryours, sent a second timeyourstrue (!)

The last row is the most instructive. Let us see what one can conclude.

What a signature proves (under assumptions)

If verification succeeds, and if the private key has not leaked and the scheme is secure:

  1. Key authenticity: the message was signed by someone holding the private key matching this public key.
  2. Integrity: the message has not been changed by a single bit since signing.

What a signature does NOT prove

  • Not a person's identity. It proves a key was used. Who holds the key? For a website, a certificate authority signs a document tying a domain name to a public key; on a blockchain you simply follow the key as a pseudonym.
  • Not the truth of the content. One can sign a lie perfectly well.
  • Not freshness. A signature carries no date. Replay (row five) stays valid: that is why transactions on account-based chains (Ethereum, and our practice network) also sign a nonce (a per-account counter) and a chain id, as in the bac-practice|chain=…|nonce=… exercise below. Bitcoin transactions carry neither an account nonce nor a chain id: the signature covers the exact output being spent, and an output already spent cannot be spent again, which plays a comparable anti-replay role.
  • Not intent. A key signed; did a human mean to sign? Malware using the key produces perfectly valid signatures.
  • Not confidentiality. The message stays readable by everyone.

A difference from HMAC

In workshop 104 you saw that an HMAC authenticates a message with a shared secret. The recipient, who knows that secret, could therefore forge a valid HMAC. With a signature the verifier holds only the public key: it can verify, it cannot sign. That is what lets a third party settle a dispute.

Recap

  • verify answers true or false for three objects: message, signature, public key.
  • True = "this key signed these bytes", assuming the key stayed secret.
  • Not identity, not truth, not freshness, not intent.

Interactive tool

ECDSA P-256 signature

Generate a key pair in your browser, sign a message, then verify the signature.

The private key is created with extractable: false: the browser keeps it in memory and never lets it be exported, and it is neither displayed nor stored. It lives only in this tab: reloading the page loses it.

Public key (SPKI, base64)

No key yet. Generate a pair to sign.

Signature (base64, P1363 format: r ‖ s, 64 bytes)

…

ECDSA with SHA-256 on the P-256 curve. WebCrypto returns r and s concatenated (32 + 32 bytes), not DER encoding.

Verify a signature

Lessons 3/4 · 15 min

Signing is not encrypting

The starting question

You often hear: "signing is encrypting with your private key". That is wrong for the schemes in this workshop, and the phrase causes real mistakes. Let us see why.

Two different goals

EncryptingSigning
Goalconfidentiality: only the right recipient readsauthenticity and integrity: everyone verifies
Who does whatencrypts with the recipient's public key, decrypts with their private keysigns with their own private key, verified with the signer's public key
The message afterwardsunreadable without the keystays readable
Useful outputa ciphertexta 64-byte signature attached to the message

In a signature the direction is therefore the reverse of encryption: the secret produces, the public part checks.

Why "encrypt with the private key" is misleading

  • ECDSA and Ed25519 are not encryption algorithms. They only know how to sign and verify: you cannot "decrypt" a signature to recover the message.
  • Even for RSA, where the picture exists historically, safe implementations use a padding specific to signatures, different from the one for encryption. Using one primitive for the other leads to flaws.
  • Good practice: one key, one purpose. Do not reuse a signing key for encryption, or the reverse.

A worked example: what an observer sees

Aminata sends to Didier over a public network:

  1. Signed, not encrypted: the observer reads "Pay 5000 CFA to Didier"; cannot alter it without breaking the signature; can copy and replay it (previous lesson).
  2. Encrypted, not signed: the observer reads nothing; but anyone knows Didier's public key and could have written this message. Didier cannot tell who sent it.
  3. Both: you get confidentiality and authenticity, with two operations and preferably two key pairs.

In a public blockchain, transactions are signed but not encrypted: everyone must be able to verify them. Encryption is not the basic mechanism there.

Your turn

In the HMAC tool, compute the HMAC of a message with the key secret1, then check that anyone who knows secret1 can produce the same value. Compare with the signing tool: here, verification does not require knowing the signing secret.

What this does NOT guarantee

Signing hides nothing. Encrypting does not prove who wrote. Neither protects against loss of the private key.

Recap

  • Encrypting = confidentiality; signing = authenticity and integrity.
  • ECDSA and Ed25519 do not encrypt.
  • A signed message stays readable.

Interactive tool

ECDSA P-256 signature

Generate a key pair in your browser, sign a message, then verify the signature.

The private key is created with extractable: false: the browser keeps it in memory and never lets it be exported, and it is neither displayed nor stored. It lives only in this tab: reloading the page loses it.

Public key (SPKI, base64)

No key yet. Generate a pair to sign.

Signature (base64, P1363 format: r ‖ s, 64 bytes)

…

ECDSA with SHA-256 on the P-256 curve. WebCrypto returns r and s concatenated (32 + 32 bytes), not DER encoding.

Verify a signature

Interactive tool

HMAC

Message authentication code: a digest that depends on a shared secret. Without the key it cannot be recomputed.

Key format
Message format

HMAC (hex)

…

An empty key is accepted (it is equivalent to a key of zeros).

Lessons 4/4 · 20 min

When the private key leaks: irreversible damage

The starting question

An employee pastes their private key into a chat group, then deletes the message thirty seconds later. Is the problem solved?

No. To see why, you must see what the network can and cannot tell apart.

Why it is irreversible

Verification tests only one thing: "does this signature match this public key?" It has no way to know who holds the private key. After a leak:

  1. The thief produces valid signatures, indistinguishable from yours.
  2. On a blockchain, they can empty the account with a single message. Confirmed transactions are not undone.
  3. As a rule there is no authority to ask to "revoke" a key: that is the very principle of the system. Your only defence is to move the funds to a new key before the thief does, and it is a race.
  4. Signatures already made stay valid. Without a trustworthy timestamp it becomes hard to say whether an old document was signed before or after the leak.

Deleting the message does not erase the copies: a bot may have read it within a second. A key that was ever visible must be treated as compromised forever.

Another way to lose the key: a failed nonce

ECDSA uses, at every signature, a one-time secret number k (an ECDSA "nonce", not to be confused with an account nonce). If two signatures use the same k, the private key d can be computed from the two. Here is the principle on a toy model: a small prime n = 23. In real ECDSA, n is about 2^256 and r comes from a curve computation; here r is simply given, because only the algebra matters.

The signature is: s = k⁻¹ · (z + r·d) mod n, where z is the message digest, r is identical for both signatures (same k) and d is the private key.

Example: d = 9 (secret), k = 5 (reused), r = 7.

  • Message 1: z₁ = 10, so s₁ = 5⁻¹ · (10 + 7·9) = 14 · 73 mod 23 = 10 (since 5⁻¹ = 14 mod 23, and 73 mod 23 = 4, 14·4 = 56 = 10 mod 23).
  • Message 2: z₂ = 3, so s₂ = 14 · (3 + 63) = 14 · 66 mod 23; 66 mod 23 = 20; 14·20 = 280 mod 23 = 4. So s₂ = 4.

The observer sees only (r, s₁, z₁), (r, s₂, z₂). They compute:

  • k = (z₁ − z₂) · (s₁ − s₂)⁻¹ = 7 · 6⁻¹ mod 23 = 7 · 4 = 28 = 5 ✔
  • d = (s₁·k − z₁) · r⁻¹ = (50 − 10) · 7⁻¹ = 40 · 10 mod 23 = 400 mod 23 = 9 ✔

Two signatures, one private key. This flaw has been exploited in real products because of faulty random generators; Ed25519 prevents it by deriving k deterministically from the key and the message (a design property of that scheme); deterministic ECDSA (RFC 6979) does the same. In our browser tool, the system's random generator does this job: its quality matters.

What this does NOT guarantee

A backup of the key (a recovery phrase, for example) protects against loss, but increases the risk of leak: each copy is a target. It is a trade-off to weigh, not a box to tick.

Recap

  • The network cannot tell the owner from the thief: it only sees valid signatures.
  • An exposed key is compromised forever; you move funds, you do not "revoke".
  • A reused ECDSA nonce reveals the private key.

Guided lab

In this lab you use your browser's signing tool (ECDSA P-256, a NIST curve; the independent lab will use ed25519). Your private key is generated in the page and never leaves your browser: it is neither displayed nor sent to the server. The server only receives the public key and the signature, which it verifies itself. The BAC practice network is a simulation: no real value.

A browser is no substitute for a real terminal: this lab trains reading and reasoning; the real hands-on practice is in the independent lab.

A certified account is required

Graded activities record results in your name and are the basis for a credential. They therefore need a complete certified file and a current consent. Filling in the file does not verify your identity; the Secretariat can verify it afterwards ("Verified" badge).

  1. 1.Build, sign and submit

    Read the generated brief: balance, nonce, recipient, minimum fee. Choose a valid fee, then build the text to sign exactly. In the tool, generate a key pair, sign that text, export the public key and the signature, and paste them into the fields. A single character of difference in the text invalidates the signature: first check in the tool that it answers "Signature VALID".

    Interactive tool

    ECDSA P-256 signature

    Generate a key pair in your browser, sign a message, then verify the signature.

    The private key is created with extractable: false: the browser keeps it in memory and never lets it be exported, and it is neither displayed nor stored. It lives only in this tab: reloading the page loses it.

    Public key (SPKI, base64)

    No key yet. Generate a pair to sign.

    Signature (base64, P1363 format: r ‖ s, 64 bytes)

    …

    ECDSA with SHA-256 on the P-256 curve. WebCrypto returns r and s concatenated (32 + 32 bytes), not DER encoding.

    Verify a signature

  2. 2.Forge and watch it fail

    In the tool, sign Pay 100 CFA to Didier. Verify: "Signature VALID". Replace 100 with 900 without touching the signature and verify again. Then generate a second key pair, keep the same signature and the original message, but verify with the second pair's public key. Note the three results, then answer the check question.

    Interactive tool

    ECDSA P-256 signature

    Generate a key pair in your browser, sign a message, then verify the signature.

    The private key is created with extractable: false: the browser keeps it in memory and never lets it be exported, and it is neither displayed nor stored. It lives only in this tab: reloading the page loses it.

    Public key (SPKI, base64)

    No key yet. Generate a pair to sign.

    Signature (base64, P1363 format: r ‖ s, 64 bytes)

    …

    ECDSA with SHA-256 on the P-256 curve. WebCrypto returns r and s concatenated (32 + 32 bytes), not DER encoding.

    Verify a signature

  3. 3.Why the nonce is signed

    Take the text from step 1: bac-practice|chain=…|to=…|amount=…|fee=…|nonce=…. Now imagine a variant without nonce or chain. A valid signature of that variant, sent twice, would stay valid both times (you saw this in lesson 2). Answer the check question about the role of these fields.

Security exercise — Two signatures, one nonce: recover the key

A small toy wallet uses ECDSA in a toy model with the prime n = 23 (the real n is about 2^256; here only the algebra is real, and r is given). Its random generator is faulty: it produced the same k for two signatures.

You observe, publicly:

Signaturerz (digest)s
11184
211192

Formulas (see lesson 4): k = (z₁ − z₂) · (s₁ − s₂)⁻¹ mod 23, then d = (s₁·k − z₁) · r⁻¹ mod 23.

Table of inverses modulo 23 (use it as is):

a1234567891011
a⁻¹1128614410318721

For a negative number, add 23 first (for example −11 becomes 12).

Compute the toy wallet's private key d and enter it. Then ask yourself: what must its owner do now, and what can they not do?

Workshop quiz

Eight questions drawn from a larger pool, 70% to pass. It opens once every lab checkpoint is passed. You can retake it: the draw changes.

A certified account is required

Graded activities record results in your name and are the basis for a credential. They therefore need a complete certified file and a current consent. Filling in the file does not verify your identity; the Secretariat can verify it afterwards ("Verified" badge).

Independent lab (outside the site)

Not graded online: do it on your own machine and publish it to your Git repository.

To do on your machine, outside the site, in a Git repository. Goal: verify a signature without reusing the demonstration code, then put it to the test.

  1. With OpenSSL (version 3 or newer), generate a test ed25519 key (openssl genpkey -algorithm ed25519), export its public key, and sign a small test file. You will find the exact options with openssl pkeyutl -help (signing a raw message needs a dedicated option).
  2. In Python, with the cryptography library, write a script verify.py that takes a public-key file, a message and a signature as arguments, and prints VALID or INVALID. Do not import the workshop's code.
  3. Test your verifier on: (a) a correct signature; (b) a message changed by one byte; (c) a signature changed by one byte; (d) the public key of another pair; (e) the test vectors published in the RFC 8032 standard for Ed25519.
  4. In a short NOTES.md file, write in a few sentences what your verifier proves and what it does not prove (identity, freshness, intent).

Never commit a private key, even a test one: add it to .gitignore as soon as you create it. Deliverable: verify.py, your test cases, NOTES.md.

Takeaways

  • A key pair is a secret private key plus a public key derived from it in one direction only.
  • A valid signature proves "this key signed exactly these bytes", nothing more: not identity, truth, freshness or intent.
  • Signing gives authenticity and integrity without hiding anything; encrypting gives confidentiality. Two purposes, two keys.
  • An exposed private key is compromised forever: the network cannot tell the thief from the owner.
  • A reused ECDSA nonce is enough to reveal the private key; randomness quality is part of security.

Common misconceptions

  • Misconception : "A valid signature proves the message comes from the person who owns the key."

    In fact : It proves that one specific private key was used. Knowing whom that key belongs to, and whether it has leaked, is a separate question.

  • Misconception : "Signing is encrypting with the private key, so the message is protected."

    In fact : A signed message remains readable by everyone. Ed25519 and ECDSA do not encrypt at all; confidentiality needs separate encryption.

  • Misconception : "If my private key leaks, I revoke it with the network and everything is back to normal."

    In fact : On a public blockchain there is generally nothing to revoke: the only defence is to move the funds to a new key before the thief does.

  • Misconception : "A valid signature cannot be reused by someone else."

    In fact : It can be replayed unchanged. That is why transactions on account-based chains (Ethereum, our practice network) also sign an account nonce and a chain id; Bitcoin gets a comparable effect because an output can be spent only once.

Glossary

Private key
A random secret number (32 bytes for P-256 and Ed25519) that lets you produce signatures. It must never be shared.
Public key
A value computed from the private key by a one-way operation; it is used to verify signatures and may be published.
Signature
A value (64 bytes in raw form for ECDSA P-256 and Ed25519) produced with the private key over a message; anyone can verify it with the public key.
Replay
Sending a valid signed message again, unchanged, at another time. The signature alone does not prevent it.
Nonce (ECDSA)
A one-time secret number k used in each ECDSA signature. Reusing it or making it predictable reveals the private key.