ecdsa.com

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.

TaskNode.jsPythonGoOpenSSLWebCrypto
Verify a signatureNode.jsPythonGoOpenSSLWebCrypto
Sign a messageNode.jsPythonGoOpenSSLWebCrypto
Generate a key pairNode.jsPythonGoOpenSSLWebCrypto
Convert DER ⇄ rawNode.jsPythonGo*WebCrypto
Verify an ES256 JWTNode.jsPythonGo*WebCrypto
Decode a certificateNode.jsPythonGoOpenSSL*
Export public key PEMNode.jsPythonGoOpenSSLWebCrypto
Key fingerprintNode.jsPythonGoOpenSSLWebCrypto

* 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, pyca cryptography, the Go standard library, the OpenSSL 3 CLI and bare crypto.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.