CAT manual

Crypto: encrypted statistics and anonymous proofs

CAT has a secure crypto chip. It encrypts your air readings so a server can compute fleet statistics without reading them, and it is being set up to prove a CAT is genuine without revealing which one.

Encrypted with a shared test keyFor now every CAT uses the same encryption key, and that key is published in the project's source code. Anyone with the source can decrypt any upload. Treat everything you upload as public. The device ID and the hour of each upload are also visible to the server.
MPC key management (in development)Secure multi-party computation (MPC) is being developed to manage the decryption key. The key will be split between several parties so that none of them can decrypt your readings alone. It will replace the test key in a future update.

The Baochip: CAT's root of trust#

Every CAT contains a Baochip, an open-hardware secure microcontroller running the Xous microkernel. It is CAT's root of trust: the chip where secrets are generated and kept, and where the cryptography runs, separate from the processors that handle the screen, radio and Wi-Fi.

  • It generates the encryption keys after each start (the roughly 4-minute Baochip busy period).
  • It encrypts your hourly air readings and decrypts fleet results (see FHE).
  • It runs the zero-knowledge prover for anonymous logins, using a secret identity that is provisioned on the chip and stays there.

What FHE means#

Fully homomorphic encryption (FHE) lets a computer do maths on data it cannot read. Your CAT encrypts its readings before they leave the device. The server adds up the encrypted readings from every CAT into an encrypted total without seeing any individual value. A key holder decrypts the total and turns it into an average.

  1. Measure. Every 3 minutes CAT records CO2, PM2.5 and PN10 (the number of particles, not their weight).
  2. Encrypt. After each full hour, the Baochip crypto chip packs that hour's 20 readings into one encrypted batch (about 3 minutes of work).
  3. Upload. CAT sends the batch over Wi-Fi to the statistics server.
  4. Combine. The platform adds every CAT's encrypted hours together and works out the spread, still encrypted.
  5. Decrypt the summary. Your CAT downloads the encrypted result (about 5 MB), the Baochip decrypts it, and the screen shows the fleet's average next to yours.

Only CO2, PM2.5 and PN10 are uploaded. VOC, NOx, temperature, humidity, pressure, light and motion never leave the device. Readings wait unencrypted in CAT's storage until they are encrypted, and are deleted after 64 hours if never sent.

What zero-knowledge proofs are#

A zero-knowledge proof (ZK proof) convinces someone that a statement is true without telling them anything else. A common example is a ring-shaped cave with a locked door in the middle: if you can enter on one side and come out on whichever side the other person names, every time, they know you can open the door, but they never learn the code.

For CAT the statement is: "I hold a secret that belongs to one of the genuine, registered CATs." The server checks the proof and learns that it is true. It doesn't learn the secret, or which of the registered CATs is asking.

PartDescription
The secretA random value provisioned into the Baochip. It never leaves the chip.
The registryA Merkle tree: every registered CAT contributes one hashed entry (a leaf), and the tree's single top hash (the root) stands for the whole set. Depth 31 holds over two billion devices.
The proof"My secret hashes to a leaf of the tree with this root," without revealing which leaf. It's computed on the CAT.
FreshnessThe server sends a random challenge (a nonce) each time, and the proof is bound to it, so an old proof can't be replayed.
Session tagThe proof also outputs hash(secret, nonce). It is the same for the whole session, so the server can recognise the login, but it changes with every nonce, so two sessions can't be linked to each other or to a device.
Technical details
  • The proof is a STARK built with battery-embedded from 0xPARC, on Plonky3: a Poseidon2 Merkle-inclusion circuit over the KoalaBear field, with a hiding FRI commitment so the proof is zero-knowledge. It needs no trusted setup and relies only on hash functions.
  • Public outputs are exactly 24 field elements: the Merkle root, the nonce, and hash(leaf, nonce) as the per-session identity.
  • The CAT keeps two secret leaves; the server supplies the path from their parent node up to the root, and the device checks the path starts at its own node before proving.
  • The Baochip runs the prover at the full depth of 31 levels, using encrypted external RAM as swap for its working memory.

Anonymous logins and uploads in development#

Today each upload is labelled with the device's factory ID (cat-nrf53-…), so the server can tell which CAT sent which hour. ZK logins are designed to remove that.

  1. Provisioning. The Baochip creates the device's secret; only its hashed leaf is added to the registry of genuine CATs.
  2. Challenge. To log in, CAT asks the server for a fresh nonce.
  3. Prove. The Baochip proves "I am in the registry" for that nonce.
  4. Verify. The server checks the proof against the registry's root and issues a short-lived access token tied to the session tag.
  5. Submit. CAT uploads its encrypted readings with that token instead of its device ID. The server learns only that the data came from a genuine CAT.

Anonymous logins are in development. The Baochip already runs the prover; logins and uploads are not yet connected to it, so uploads still carry the device ID.

Settings → CRYPTO. Only one job runs at a time; choosing a job that is already running shows its progress.

Before any statistics have been fetched.
With a report available and both hourly options ticked.
RowWhat it does
UPLOAD LAST HOUREncrypt and upload the last complete hour now.
FLEET STATSRun the fleet job now and show the result.
VIEW LAST STATSShow the most recent fleet report again (only listed once there is one).
FHE HOURLY UPLOADUpload every hour automatically. Off by default.
FHE HOURLY STATS DOWNLOADFetch fresh fleet statistics every hour automatically. Off by default.

The bottom line reads Wi-Fi: yes Keys: yes Job: idle: whether CAT is online, whether upload credentials are installed, and whether a job is running. If CAT doesn't answer it says Nordic: no reply.

Uploading an hour#

UPLOAD LAST HOUR opens a progress page with two steps, encrypting and uploading. A tick marks a finished step, a triangle the current one, and a red cross the step that failed. On real hardware encryption takes about 3 minutes.

Encrypting.
Uploading.
Uploaded.
Each hour is uploaded only once. Asking again says Already uploaded.

Press B to leave the progress page; the job carries on.

Fleet statistics#

FLEET STATS runs five steps: requesting, computing (the platform works on the encrypted data), downloading and loading (with a percentage), then decrypting. On hardware the whole job takes about 10 minutes. When it finishes, the statistics screen opens.

Computing on the platform.
Downloading the encrypted result.
The statistics screen, styled like the Dashboard's LIVE STATISTICS.
  • The top bar shows how many CATs contributed.
  • Each row is one measurement: PM 2.5, PN 10 and CO2.
  • You (pink) is the average of your last uploaded hour. Fleet (blue) is the average of every reading from every CAT, ± the spread (standard deviation).
  • PM 2.5 and CO2 get letter grades and sit on the same colour bar as the Dashboard. PN 10 has no grade and uses a plain scale.
  • On the bar, the pink triangle is you, the blue tick is the fleet average, and the light blue band covers the fleet's spread.
  • -- means there is no value, for example no uploaded hour of your own yet.

Press B or tap to go back. With no report yet the screen says No fleet stats yet.

Before your own hour is included: You shows --.
VIEW LAST STATS appears once a report exists.

Hourly automation#

  • FHE HOURLY UPLOAD: from the hour you tick it, each completed hour is encrypted and uploaded. Older hours are not back-filled. If an upload fails, CAT retries after 2, 5, 10, 20, 30 and 60 minutes. Being offline or busy doesn't count as a failure.
  • FHE HOURLY STATS DOWNLOAD: once an hour, from 20 minutes past (after the uploads have landed), CAT runs the fleet job in the background. If it is busy or offline it tries again every 2 minutes, up to 3 runs an hour. You don't see progress; open VIEW LAST STATS for the new numbers.
  • Both settings live on CAT and survive restarts.

Status and error messages#

A server refusal: HTTP 401 with the internal error number.
Another job is running.
MessageMeaning
Uploaded / DoneSuccess.
Already uploadedThat hour was sent before. Nothing to do.
No Wi-FiConnect to Wi-Fi first (how).
No tokenNo upload credentials are installed.
HTTP 401 (or another number)The platform refused the request.
Baochip busyThe crypto chip is still generating keys, which takes about 4 minutes after every start. Try again later.
BusyAnother upload or fleet job is running.
No dataNo complete hour of readings yet, or no fleet readings.
No clockCAT doesn't know the time yet.
Job failed / TimeoutThe platform job failed or took too long (the limit is 20 minutes).
Decrypt failed / Baochip errorThe crypto chip couldn't decrypt or summarise the result.
Network errorThe connection failed partway.
Storage errorCAT couldn't store the result.
No reply / Not supportedCAT didn't answer, or its firmware doesn't know this request.

Privacy#

  • Encrypted in transit and at the server: your CO2, PM2.5 and PN10 values for each hour, plus whether each reading was valid and how many readings passed fixed health thresholds.
  • Visible to the server: your device ID (until ZK logins replace it), which hour the batch is for, when and how much you uploaded, and some plain bookkeeping (counts of valid readings and the units).
  • Not protected yet: because the key is shared and public, anyone with the project's source can decrypt your uploads. With only a few CATs taking part, the fleet average can also reveal a lot about each one.

Leave both hourly options off unless you are happy for your hourly air readings to be effectively public. MPC key management will replace the shared test key in a future update.