Skip to content
Concepts

Signatures

What BatteryPass signs in each passport version, how the hash and the Ed25519 signature are computed, and how to check them with the published keys.

Every published passport version is signed, so anyone can check that the data comes from your BatteryPass installation and was not changed afterwards. The check needs no account and no call to BatteryPass: the public JSON and the published keys are enough.

What is signed

At publication BatteryPass signs two documents of each version with the active key, in the same transaction that stores them:

DocumentContainsHash and signatureWhere to read it
Public documentThe public tier projection, with labelspublic_hash, public_signaturedocument and verification of the public JSON (getPublicPassport); public_document of getPassportVersion
SnapshotEvery field in every tier, with provenance and document referencescanonical_hash, signaturesnapshot of getPassportVersion, for your organisation

The public document is what a scanner sees, so anyone can verify it. The snapshot proves the full record to you and to authorities you show it to. In the public JSON only document is signed; its siblings passport_id, status, valid_until, verification and links change over the passport's life and are not covered.

verification
{
  "algorithm": "Ed25519",
  "canonicalization": "RFC8785",
  "hash": "sha256:22471733ece6d811d244144731fc505180c5e7760a7a016c1322338bce0f56e5",
  "signature": "w0nnz3kjhrEGb1DtMoGp9qlH9g8q0h9YDJRb2jfabq7AOzPMUpnWXoxmIlptgJPTDVy3LWxLQkOpQYuGYXgJ4w",
  "key_id": "2027-10-k2",
  "signed_at": "2026-10-24T09:15:02Z",
  "keys_url": "https://batterypass.example.com/.well-known/batterypass/keys.json"
}

How a signature is made and checked

Canonicalise

Serialise the signed object (document, or snapshot) with the JSON Canonicalization Scheme, JCS (RFC 8785). JCS sorts object members, drops whitespace and writes numbers and strings in one defined form, so the same data always gives the same bytes. Canonicalise the parsed object, not the response bytes.

Hash

Compute SHA-256 over the canonical bytes and write it as sha256: followed by the lowercase hex digest. It must equal verification.hash (or public_hash, canonical_hash).

Find the key

Fetch the JWK set from /.well-known/batterypass/keys.json of the BatteryPass address you trust and take the key whose kid equals verification.key_id. keys_url is not signed: if it points to another address, treat the check as failed.

Verify

Decode the key's x and the signature from base64url without padding (32 and 64 bytes) and check the Ed25519 signature over the canonical bytes, not over the hash.

The signature verification guide does this step by step with complete code.

The published keys

The public keys are a JWK set at /.well-known/batterypass/keys.json on your BatteryPass address, outside /api/v1. It needs no key, may be read from any origin (CORS) and is cacheable for an hour.

keys.json
{
  "keys": [
    { "kty": "OKP", "crv": "Ed25519", "x": "WuoaQRoQuh2kPs5yYB6HxNz3Y58ndE8fRHnzG10NxoU", "kid": "2027-10-k2", "use": "sig", "alg": "EdDSA" },
    { "kty": "OKP", "crv": "Ed25519", "x": "JEpD6r2NnmNrL4_7UWS9wIWLFyjCfaSClypHm110Vl4", "kid": "2026-10-k1", "use": "sig", "alg": "EdDSA" }
  ]
}

The active key is listed first. The operator of your installation rotates keys: a new key signs new versions, and the old public keys stay in the set so earlier signatures keep verifying. A key that signed a published version is never removed. Cache keys by kid and fetch the set again when you meet an unknown kid.

Verifying on the server or offline

verifyPassportOffline verification
What it checksBoth signatures and both hashes of a version against the stored documentsThe public document you hold, against the published key
Resultvalid, public_document_valid, snapshot_valid, key_id, version_no, signed_at, checked_atYour own yes or no
TrustYou trust the server's answerYou trust only the key, which you can pin
NeedsThe passport UUID; version_no optional (default: current version)The public JSON and the JWK set

verifyPassport is a convenience for a quick check. For an independent proof, for example in an archive or a customer's system, verify offline.

A valid signature shows that this BatteryPass installation published exactly this data in this version. It does not say that the data is correct or complete, and it is not a qualified electronic seal under eIDAS.

On this page