Repository navigation
Right-only ORE storage for unindexed stores (queues, columnar) — needs a trinary indicator #99
Description
Background
ore.rs implements Lewi–Wu block ORE (order-revealing encryption): a ciphertext has a left half (deterministic per-block tags and permuted symbols) and a right half (a random nonce plus masked indicator bits). A comparison takes one side's left half and the other side's right half. Comparing two stored rows therefore needs their left halves.
Every scheme stores full ciphertexts (left + right), and for a database column that is not a choice: a B-tree index compares stored rows with each other when it is built and maintained, which is only possible if each row carries its left half. The consequence is inherent to an indexed column, not a gap: anyone holding the data can order the rows (and, for the chained string scheme, learn the common-prefix length of any two) with no query, exactly as the index itself does. #83 documents this in plan §5(b)/§9 and the chained module docs.
Problem
Not every store is an indexed Postgres column. Messages on a queue, event streams, and columnar warehouse storage (Parquet, Iceberg and the like) are scanned rather than B-tree indexed, and for those a stronger at-rest posture is available: store right halves only. A stolen queue or Parquet file then reveals nothing about order; only a holder of the key can produce a left half and compare it against the stored rights, one row at a time.
That deployment doesn't exist today:
- A comparison from a query's left half and a stored right half alone has to settle "equal" from the right block, which the current one-bit indicator cannot express; today the first differing block is found from the left halves of both sides.
- The right half has no standalone artefact: the chained
VarRighthas no serialise, parse or compare API, and neither legacy Bit8 nor Bit6 has a left-versus-right-only comparator.
Proposal
- Design a right-only storage artefact and a left-versus-right comparator. That needs a trinary indicator (less / equal / greater) in the right block — the old README's 1.0 roadmap item, "avoids needing to store left-ciphertexts" — which is a wire-format change, so it must be decided before Bit6 and chained are frozen. Legacy Bit8 is frozen and out of scope.
- The comparator is sequential-scan only, by construction. Document that a right-only column cannot be indexed, and that this is the option for queues, streams and columnar stores, not a replacement for the indexed default.
- Once it exists, restore plan §5(b)'s at-rest tier and the deployment table's "right-only" row, scoped to those stores.
Relationship to other work
- ORE v2 (6/n): chained-prefix variable-length scheme + string encryption #83: documents the indexed-column exposure as inherent, and the chained scheme this would extend.
- ORE v2 (5/n): 6-bit block scheme + v2 wire format #82: Bit6, the other unfrozen format the indicator change would reach.
Activity
[-]Stored ORE ciphertexts can be compared offline — design right-only storage[/-][+]Right-only ORE storage for unindexed stores (queues, columnar) — needs a trinary indicator[/+]docs: right-only storage is secure but not yet supported