HarmonyPIR — relocation and the permutation
The previous page left a loose thread. The query into segment
s revealed most of that segment to the server — every
real DB index in it except the one at the target's slot, which got
replaced by a random cell from outside. The target itself stays
hidden behind the client's hint XOR, so a single request leaks
nothing about what was asked for. The danger is reuse: if the client
later needs to fetch another index whose original home is segment
s, the protocol would have to use segment s
again, and the two requests would look nearly identical — the same
(T−1) real cells from segment s, just a different
position swapped out for a different outside cell. Correlating the
two lets the server reverse-engineer which position was "the
replacement" each time, pinning down the permutation. So segment
s has to retire after one use. But the DB indices it
held still need to be reachable — they have to be re-homed into
other segments.
Concretely: the real values in segment s (two in our
running example; in general up to T) each move to a
fresh random empty cell somewhere else in the hint row, one at a
time. Segment s becomes all ⊥. The client
updates its stored parities to match — each segment that received
one of the moved values gets that entry XOR-ed into its parity. Once
the bookkeeping is done, the hint table is back to the same shape
it had before, only permuted differently and with fewer empty cells
left over.
The permutation backend
A design choice in HarmonyPIR is to use one random
permutation of size 2N for the entire hint row, rather
than separate per-partition shuffles. This lets the scheme plug in
any off-the-shelf PRP large enough to cover the domain.
What BitcoinPIR actually wires in
The harmonypir crate keeps the permutation behind a
Prp trait and ships two backends, each with a different
trade. The BitcoinPIR SDK exposes the choice as a runtime flag,
with FastPRP the production default.
- HMR12. An AES-based card-shuffle PRP with a security reduction to AES; BitcoinPIR uses a tweaked variant (Algorithm 5 in the HarmonyPIR paper) that cuts AES calls by ~4× per evaluation via phase grouping. Pure AES, no extra dependencies, compiles cleanly to WASM. ~6 µs/op native, ~14 µs/op in a browser. Works at any database size. Based on Hoang, Morris & Rogaway, An Enciphering Scheme Based on a Card Shuffle (CRYPTO 2012) — hence the shorthand HMR12.
- FastPRP (default). A small-domain PRP that
builds a permutation cache (~60 ms at
N≈ 6M) and answers subsequent evaluations inO(√N log N); ideal for the server's one-off offline hint generation over many groups at once. Implements Stefanov & Shi, FastPRP: Fast Pseudo-Random Permutations for Small Domains (ePrint 2012/254).
Earlier versions of the SDK also shipped an ALF backend (Wang, Maximov & Johansson, Introducing the ALF family, ePrint 2025/2148). ALF was retired in May 2026 because its implementation panicked on domains smaller than 216, which the sibling-Merkle hint tables routinely hit. FastPRP is now the default; HMR12 remains as a pure-AES alternative.
The BitcoinPIR deployment runs HarmonyPIR per cuckoo-hash group: 75 INDEX groups plus 80 CHUNK groups in the current parameters, each with its own hint row and its own PRP instance, all under a single master client key. The group structure comes from the batch-code layer two sections from now — same pattern for every backend, so we'll cover it once there.