Public Keys & Signatures

Published on:

Most important commands to remember

  • openssl pkeyutl -sign — create a signature using a private key.
  • openssl pkeyutl -verify — check it using the public key.

Commands and flags

Command or option Meaning
mktemp -d Create a private temporary directory; signature_lab=$(…) saves its path.
genpkey -algorithm ED25519 -out FILE Generate a disposable Ed25519 private key.
pkey -in FILE -pubout -out FILE Export its public key.
pkeyutl -sign / -verify Sign / verify the input message.
-rawin -inkey FILE -in FILE Use message bytes directly with Ed25519 and select key and message.
-pubin / -sigfile FILE Read a public key / select the signature to verify.
printf '…\n' > FILE Write text and newline into the disposable message file.
rm / rmdir Remove named example files / their empty directory.

Quoted variables preserve paths. > replaces only the example message. This private key is unencrypted and disposable, not a production credential.

The concepts that matter

1. A key pair has different roles

A private key performs operations that require secret possession. Its corresponding public key can be shared for verification. In this example, Ed25519 is a signature algorithm, not an encryption scheme.

Keeping the public key secret adds no required protection to this verification model. Keeping the private key secret is essential: someone who obtains it can create signatures accepted under that public key.

2. A signature authenticates bytes, not their meaning

A digital signature lets a verifier check whether particular bytes were signed with the matching private key and remained unchanged. It does not encrypt the message or prove that its contents are true.

A correctly signed malicious command is still malicious. Authorization must decide whether this signer may request that action, and the application must interpret the message safely.

3. Exact representation matters

Changing a newline, encoding, field order, or other byte changes the signed input unless the protocol defines a canonical representation. Signing parsed JSON and verifying differently formatted JSON can therefore fail.

The signature scheme handles its cryptographic processing. Do not casually add a separate hash or encoding step that the verifier does not expect. Both sides must implement the same defined scheme.

4. Verification needs an authentic public key

An attacker can generate a new key pair and sign a replacement message. Verification will succeed if you also accept the attacker’s replacement public key.

The important trust question is where the verification key came from: a certificate chain, pinned configuration, or another authenticated distribution mechanism. Cryptographic validity and trusted signer identity are separate checks.

One small example

Optional: run each line in one Bash terminal after directory creation succeeds. Continue through the deliberately failed second verification to cleanup.

signature_lab=$(mktemp -d)
openssl genpkey -algorithm ED25519 -out "$signature_lab/key.pem"
openssl pkey -in "$signature_lab/key.pem" -pubout -out "$signature_lab/public.pem"
printf 'hello\n' > "$signature_lab/message.txt"
openssl pkeyutl -sign -rawin -inkey "$signature_lab/key.pem" -in "$signature_lab/message.txt" -out "$signature_lab/signature.bin"
openssl pkeyutl -verify -rawin -pubin -inkey "$signature_lab/public.pem" -in "$signature_lab/message.txt" -sigfile "$signature_lab/signature.bin"
printf 'changed\n' > "$signature_lab/message.txt"
openssl pkeyutl -verify -rawin -pubin -inkey "$signature_lab/public.pem" -in "$signature_lab/message.txt" -sigfile "$signature_lab/signature.bin"
rm "$signature_lab/key.pem" "$signature_lab/public.pem" "$signature_lab/message.txt" "$signature_lab/signature.bin"
rmdir "$signature_lab"

The first verification should succeed for the original bytes. After replacing the message, verification should fail and return nonzero. These are expected outcomes to check, not captured results. If key generation or signing fails, resolve that earlier error before interpreting verification.

The final two lines remove the private key, public key, message, signature, and empty directory. They normally print nothing. No trust store or existing key is modified.

Keep this idea: A signature proves a relationship between bytes and a key; you must separately trust that key and authorize its use.