ECDSA how-to: task × language
Short, working recipes for the ECDSA jobs that come up in real projects: verify a signature, sign a message, generate a key pair, convert a DER signature to raw r‖s, verify an ES256 JWT, decode an X.509 certificate, export a public key as PEM and compute a key fingerprint — each in Node.js, Python, Go, the OpenSSL CLI and browser WebCrypto.
Every snippet was executed against real tools before publication, and recipes are cross-checked between languages — a signature produced by the Python recipe verifies with the Node.js one, a Go signature verifies with OpenSSL, and a WebCrypto signature verifies in Node. Where a language has no honest native answer, the cell says so instead of pretending.
| Task | Node.js | Python | Go | OpenSSL | WebCrypto |
|---|---|---|---|---|---|
| Verify a signature | Node.js | Python | Go | OpenSSL | WebCrypto |
| Sign a message | Node.js | Python | Go | OpenSSL | WebCrypto |
| Generate a key pair | Node.js | Python | Go | OpenSSL | WebCrypto |
| Convert DER ⇄ raw | Node.js | Python | Go | —* | WebCrypto |
| Verify an ES256 JWT | Node.js | Python | Go | —* | WebCrypto |
| Decode a certificate | Node.js | Python | Go | OpenSSL | —* |
| Export public key PEM | Node.js | Python | Go | OpenSSL | WebCrypto |
| Key fingerprint | Node.js | Python | Go | OpenSSL | WebCrypto |
* Why some cells are empty
Convert DER ⇄ raw × OpenSSL: The openssl CLI has no command that re-encodes an ECDSA signature: asn1parse can dump r and s but nothing reassembles them. Use the browser DER ⇄ raw converter or one of the language recipes.
Verify an ES256 JWT × OpenSSL: A JWS ES256 signature is raw r‖s, and openssl dgst only consumes DER — rebuilding the DER requires scripting outside openssl itself. The JWT debugger verifies ES256 tokens in the browser instead.
Decode a certificate × WebCrypto: WebCrypto has no ASN.1 or certificate parser — importKey accepts bare SPKI keys only. In the browser, use a library such as @peculiar/x509 (which powers our certificate decoder).
The in-browser alternatives: DER ⇄ raw converter, JWT ES256 debugger and X.509 certificate decoder.
How these recipes are written
- Standard tooling only:
node:crypto, pycacryptography, the Go standard library, the OpenSSL 3 CLI and barecrypto.subtle— no wrapper packages to fall out of date. - Interop first: every page states whether its signatures are ASN.1 DER or raw r‖s, because mismatched encodings — not broken keys — cause most "invalid signature" errors. The byte-level background is in ECDSA signature formats.
- Each recipe links the browser tool that checks its output — signature verifier, converter, JWT debugger — so you can confirm results without writing more code.