ecdsa.com

Sign a message · OpenSSL

How to sign a message with ECDSA with OpenSSL

openssl dgst signs a file with ECDSA in one command: hash choice, private key, output file. The result is a binary ASN.1 DER signature — the format every OpenSSL-lineage stack expects, and the one you must convert if the consumer is WebCrypto or a JWT library.

Tested with OpenSSL 3.6.

Same recipe in:Node.jsPythonGoOpenSSLWebCrypto
sign a file with SHA-256
openssl dgst -sha256 -sign key.pem -out sig.der message.txt
check the round trip immediately
openssl pkey -in key.pem -pubout -out pub.pem
openssl dgst -sha256 -verify pub.pem -signature sig.der message.txt
# Verified OK
make the binary signature transportable
openssl base64 -in sig.der # base64 for JSON / email
xxd -p sig.der | tr -d "\n"; echo # hex, one line
openssl asn1parse -inform DER -in sig.der # shows r and s

How it works

  1. -sign takes the private key PEM (PKCS#8 or SEC1 — both work) and implies ECDSA for an EC key.
  2. The hash flag is part of the contract: the verifier must use the same -sha256. For P-384 keys, -sha384 is the conventional pairing.
  3. Output is raw binary DER, 70–72 bytes on P-256 — write it with -out, never copy it from the terminal.

Gotchas

  • The signature is binary: pasting it into a text field corrupts it silently. Base64- or hex-encode first (third snippet), and decode before verifying.
  • DER length varies between 70 and 72 bytes on P-256 — length-validating code that expects one fixed size will reject valid signatures.
  • Signing twice gives different bytes each time (random nonce). To compare signatures across runs, verify each one — never diff them.

Related recipes