Skip to content
QRalo

Security

How QRalo verification works

Each code carries its own Ed25519 signature. Scanning it opens qralo.com, which checks that signature against your organization’s public key before it shows a name or an address.

What the camera reads440 chars

https://qralo.com/verify?qr=eyJ2IjoxLCJpZCI6IjdjMWU0YjJhLTBkNWYtNGU4Yi05YTYxLTNmMmQ4YzBiNWUxNyIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vcGF5L21ldGVyLTA0MjMiLCJjb250ZXh0IjoiUEFSS0lORyIsIm9yZyI6ImIzYTlkNmUwLTQxYzItNGY3YS04ZTE1LTZkMmM5MGE0ZjM4MSIsImlhdCI6MTc5MzYxMTIwMCwiZXhwIjoxODI1MTQ3MjAwLCJsb2MiOiJNZXRlciAwNDIzIiwic2lnIjoibVN0cVhLc0FDeHFRdGdqZk8rem5xYmxadUVIeElWaTBJSjZ3ODZBWGtyemgwTkpWbDMrTUYwZzRwSG5HcGxzeUkrNjdVZlZzV0FSc3h1UGZmSStzQ0E9PSJ9

A complete signed code for “Meter 0423”. The part after qr= is decoded in section 01.

01Anatomy

What’s in a signed code

The part after qr= is JSON, encoded in base64url. Anyone can decode it and read the destination. Nothing in it is encrypted.

payload.jsonDecoded
"v": 1,
Protocol version.
"id": "7c1e4b2a-0d5f-4e8b-9a61-3f2d8c0b5e17",
The code’s own ID. The server uses it to look up whether the code is active, expired or withdrawn.
"url": "https://example.com/pay/meter-0423",
The destination. Change it and the signature no longer matches.
"context": "PARKING",
The purpose you picked: MENU, PARKING, PAYMENT, DELIVERY, EVENT or OTHER.
"org": "b3a9d6e0-41c2-4f7a-8e15-6d2c90a4f381",
The organization that signed the code. The server uses it to find the public key.
"iat": 1793611200,
When the code was signed, in Unix seconds. Here, 2 November 2026 at 09:20 UTC.
"exp": 1825147200,
Optional expiry date. After it, the page shows the code as expired. Here, 2 November 2027.
"loc": "Meter 0423",
Optional label, so people can match the code to the meter or table in front of them.
"sig": "mStqXKsACxqQtgjfO+znqblZuEHxIVi0IJ6w86AXkrzh0NJVl3+MF0g4pHnGplsyI+67UfVsWARsxuPffI+sCA=="
The Ed25519 signature over every field above. 64 bytes, 88 characters in base64.
This example uses the exact format of a real code. It was signed with a throwaway key that QRalo doesn’t know, so qralo.com rejects it. The IDs and the destination are made up.

The signature covers the exact text of every field except sig. Edit one character, say Meter 0423 to Meter 0424, and the check fails.

02On each scan

What qralo.com does before it shows anything

Six checks, in this order, every time someone scans.

  1. Decode

    The camera opens qralo.com/verify and our server decodes the payload. Anything that isn’t a QRalo payload stops here.

  2. Find the key

    The server looks up the organization named in org and loads its public key. An unknown organization means an invalid code.

  3. Check the date and the signature

    A code past its exp date shows as expired. Otherwise the server checks the Ed25519 signature against the public key.

  4. Check the status

    A code you revoked shows as withdrawn. On the Free plan, a code past 100 scans shows as paused.

  5. Check the link

    The destination goes through the link checks in section 04. The server also looks up whether the organization verified its domain.

  6. Show the result

    The name and destination appear only when the signature is valid. The page opens the destination by itself only for a verified domain and a low-risk link, after a 5-second countdown.

Every check runs online. A revoked code shows as withdrawn from the next scan, wherever it’s printed. Without a connection, a phone can’t check a code.

03Before you print

What a valid signature tells the person scanning

It shows

  • The code was signed by the QRalo account on screen, and whether that account verified its domain with a DNS TXT record.
  • Nobody has changed the destination, purpose, label or dates since the code was signed.
  • Whether the code is active, expired or withdrawn right now.

It can’t show

  • Whether a fake was stuck over your code. A fake can’t open qralo.com with your verified name, so put “Scanning opens qralo.com first” on your signs. Look-alike addresses such as qra1o.com are a warning sign.
  • Who runs an account with no verified domain. Until the domain is verified, the name is whatever the account typed.
  • Whether the destination sits on the verified domain. QRalo doesn’t compare the two yet.
  • Whether a website is harmless. The link checks in section 04 flag common phishing patterns.

A photocopy of a genuine code still checks out, because it is the same signed code with the same destination. A scammer’s own code can’t carry your verified name.

05Keys and accounts

Keys, revocation and accounts

One key pair per organization

When you sign up, QRalo generates an Ed25519 key pair for your organization. The private key is stored encrypted with AES-256-GCM and only signs your codes. You never handle it, so you depend on our servers to keep it secret.

Revocation and expiry

Revoke a code in the dashboard and the next scan shows it as withdrawn, wherever it’s printed. The expiry date sits inside the signed payload, so a later date means a new code. A new destination means a new code too.

Accounts

Passwords are stored as bcrypt hashes. You sign in with email and password, or with Google. Sign-in attempts and code creation are rate-limited. Our servers are hosted by Hetzner in Germany.

Not available yet

Two-factor authentication, single sign-on, an audit log and key rotation. QRalo has not been through a third-party security audit or certification.

06Privacy

What a scan records

Scanning needs no account. Each check records four things, for the issuer’s statistics and to limit abuse.

Legal bases, retention and your rights are in our Privacy Policy.

Time and result
When the code was scanned and what the verification page showed.
Browser information
The user-agent string, from which we derive the device type and browser.
Pseudonymized IP address
A salted SHA-256 hash of the IP address, shortened. It is pseudonymized and can still count as personal data.
Approximate location
City, country and approximate coordinates. To get them, the IP address is sent at scan time to ipapi.co, a third-party geolocation service.

07Responsible disclosure

Report a vulnerability

Found a security issue in QRalo? Email us with “Security” in the subject line, with the steps to reproduce it.

  • Test only with accounts and codes you own.
  • Don’t access, change or delete other people’s data.
  • Don’t run denial-of-service tests or automated scans that slow the service down.
  • Give us reasonable time to fix the issue before you make it public.

We’ll acknowledge your report and keep you posted on the fix. There is no paid bug bounty.

Email a reportcontact@qralo.com

Sign one code and scan it yourself

It takes a few minutes. You’ll see exactly what your customers will see.

3 signed codes free. No card.