Abast
Opcional, darrere d'un feature de compilació, i fixat en la creació del fitxer: activar-ho més tard significaria reescriure cada pàgina.
Algorisme
ChaCha20-Poly1305 per defecte, AES-256-GCM seleccionable. El valor per defecte segueix la divisió entre els entorns de destinació: amb acceleració per maquinari, AES-GCM arriba a 1-2 GB/s i xifrar una pàgina de 4 KB costa 2-4 μs; sense ella — processadors IoT sense extensions criptogràfiques — l'AES per programari cau a 50-100 MB/s, i aquesta mateixa pàgina costa 40-80 μs. ChaCha20 sense acceleració manté 200-400 MB/s, és a dir, 10-20 μs.
Tots dos utilitzen les implementacions de RustCrypto — Rust pur, compatibles amb no_std — que afegeixen 60-100 KB al binari, i es compilen només quan el feature està actiu. inro no implementa les seves pròpies primitives criptogràfiques: la dependència que s'estalvia no compensa el risc.
Aquesta és l'única excepció a la política per defecte de zero dependències del projecte, i porta una advertència que val la pena dir sense embuts: forbid(unsafe_code) no arriba a les dependències, i aquests crates fan servir unsafe en la detecció de característiques de la CPU i en els seus backends SIMD. La fase 1 ha d'avaluar si el backend portable de ChaCha20 pot prescindir d'aquest unsafe, i a quin cost de rendiment — mesurat, no assumit.
Disposició de la pàgina xifrada
0 8 comptador del nonce (en clar: necessari per re-derivar el nonce)
8 16 etiqueta d'autenticació
24 .. text xifrat de la pàgina lògica completaEl nonce es deriva, no s'emmagatzema: nonce = page_number (u32) || counter (u64), exactament 12 bytes. El comptador és un comptador d'escriptura monòton i persistit — no el txn_id de la transacció — reservat per endavant per a cada escriptura de pàgina i registrat a les dues pàgines meta. L'etiqueta substitueix el CRC32, que passa a ser redundant — una pàgina corrupta o manipulada falla l'autenticació en el seu lloc.
Sobrecost net: 20 bytes per pàgina — 0,5% amb pàgines de 4 KB, 3,9% amb pàgines de 512 B. Un node de 31 MB amb pàgines de 4 KB paga 155 KB.
L'invariant del nonce
page || counter és únic sempre que el comptador no es reutilitzi per a la mateixa pàgina — una garantia que imposa qui reparteix els comptadors, no una cosa que el disseny copy-on-write proporcioni per si mateix.
Una versió anterior d'aquest disseny derivava el nonce a partir de page || txn_id, raonant que el copy-on-write ja garanteix la unicitat: una pàgina bruta es modifica en RAM i es bolca exactament un cop, en el commit. Això val per a una transacció que escriu cada pàgina com a molt un cop — però txn_id és el mateix per a totes les pàgines d'una transacció, i una pàgina es pot escriure més d'un cop dins d'una mateixa transacció (alliberar una pàgina i reassignar-la abans del commit reutilitza el seu número de pàgina), la qual cosa reutilitzaria aquest txn_id i, per tant, el nonce. En lloc d'això, inro reserva un comptador d'escriptura dedicat per a cada escriptura de pàgina, de manera que aquest cas no es pot donar: el parell (page, counter) mai es repeteix, independentment de quantes vegades es reescrigui la mateixa pàgina dins d'una transacció.
Si el comptador es reutilitzés algun cop — un error en com es reserva, o un bolcat intermedi que no l'avança — això trenca la confidencialitat de les dues pàgines tant amb ChaCha20-Poly1305 com amb AES-GCM, i pot permetre falsificar l'etiqueta. Es manté com un invariant documentat, amb un test automatitzat que falla si mai es viola.
Gestió de claus
El motor rep 32 bytes, ja derivats. Derivar-la a partir d'una contrasenya queda fora d'abast: significaria incorporar Argon2 — pesat en RAM, inadequat per a IoT — o PBKDF2, i aquestes són decisions que no li corresponen a un motor d'emmagatzematge. A l'edge la clau arriba des del pla de control durant l'aprovisionament; a IoT, des de l'arrencada segura o la configuració.
La rotació funciona per embolcall: la clau que rep el motor és la clau master, i embolica una clau data per fitxer, emmagatzemada xifrada a les dues pàgines meta. Rotar la master reescriu aquests bytes a les dues metes, no el fitxer sencer. Rotar la clau data sí que implica reescriure el fitxer, i només cal si se sospita que s'ha filtrat.
El que no protegeix
La capçalera de 64 bytes es manté en clar, perquè la mida de pàgina s'ha de conèixer abans de poder desxifrar res. El que es filtra: que el fitxer és una base de dades inro, la seva versió de format, la seva geometria, la seva mida total, el nombre de transaccions realitzades, i el patró d'accés. Les claus i els valors dins de les pàgines estan xifrats, així que ni la seva longitud ni el seu contingut es filtren.
El xifratge protegeix contra el robatori del disc, la còpia d'una còpia de seguretat, i l'accés del proveïdor d'allotjament. No protegeix contra un procés comprès, perquè la clau viu a la seva memòria.