Understanding Signatures
Nopan requires every request and response to be digitally signed.
This ensures three critical security guarantees:
- Authenticity - only the holder of the private key could have created the signature.
- Integrity - any modification of the request or response payload invalidates the signature.
- Non-repudiation - a party cannot later deny having sent a signed message.
This guide explains the concepts behind signatures so that you can better understand how they are built and verified.
What is a Digital Signature?
A digital signature is a cryptographic proof attached to an HTTP message.
It is created by applying a private key to a canonicalized message string (the signature base) and sending it along with http headers.
The recipient verifies it with the matching public key.
- Private key : Used only by the client, must be kept secret.
- Public key : Shared with Nopan to allow verification.
- Signature base : Canonical representation of important HTTP fields.
- Signature : Base64-encoded output of signing the base with your private key.
The signature doesn’t change the content - it proves who sent it and that it hasn’t been tampered with.
Anatomy of a Signature
A signature in Nopan is represented by two HTTP headers:
SignatureSignature-InputWe follow the RFC-9421 specification recommendations for HTTP Message Signatures. For more details, refer to this document.
Example
Signature: nopan_sig=:lP3D...kQ==:
Signature-Input: nopan_sig=("@authority" "@method" "@request-target" "content-digest" "content-type" "content-length");keyid="your-key-id";created=1766678793
nopan_sigis the label for the signature instance.keyidtells Nopan which key to use to verify the signature.createdis a UNIX timestamp (seconds) in UTC when the signature was created.
What is the Signature Base?
The signature base is the exact string that gets signed.
It is built by combining selected HTTP headers and pseudo-headers in a strict, ordered format, each on a new line.
It's crucial that both the client and the server construct this string in the exact same way.
- Each component follows the format `"component-name": value`
- Component names (but not values) are always lowercased
- Each component is placed on its own line
- Each line is concatenated with a newline character (\n), hex value 0x0a. There is no trailing newline.
Components of HTTP signature base
Constructing @signature-params
All components are taken either from headers or pseudo headers, except for @signature-params.
To construct it, take the name of the signature (nopan_sig), add a = sign, and concatenate
signature inputs using ; as a separator.
Example:
"@signature-params": nopan_sig=("@authority" "@method" "@request-target" "content-digest" "content-type" "content-length");keyid="your-key-id";created=1766678793
Once the signature base is constructed it should look like this:
"@authority": api.nopan.com
"@method": POST
"@request-target": /payments/initiate
"content-digest": sha-256=:Base64EncodedHashOfBody==:
"content-type": application/json
"content-length": 123
"@signature-params": nopan_sig=("@authority" "@method" "@request-target" "content-digest" "content-type" "content-length");keyid="key";created=1766678793
Request vs Response Signatures
While the principle is the same, the components included differ:
Signature component usage
This ensures both request authenticity and response authenticity.
Why Strict Canonicalization Matters
Even a minor change - like an extra space, uppercase method name, or different header order - would produce a completely different hash.
That’s why canonicalization rules are strict: both client and server must generate the exact same signature base to validate each other.
If your integration fails signature validation, the first thing to check is whether your signature base string is built identically to Nopan’s expectations.
Putting it All Together
Here’s how the signing process fits conceptually:
- Select required components (headers & pseudo-headers).
- Build the signature base string.
- Sign it with your private key.
- Attach the
SignatureandSignature-Inputheaders. - Nopan validates using your public key.
And in reverse for responses: Nopan signs the response, and you validate using Nopan’s public key.