\(\Fsig \) said plainly that it does not authenticate the key it hands out — \(\opl {Verify}\) takes a \(\vk \) of its own, unconnected to any caller, because verification keys are not assumed authenticated (Section 15.1). The functionality \(\Gpki \) below is the setup that closes the gap, in the shape of Canetti’s own certification functionality [6]: a single, shared directory binding a key to the party that claims it, so that a \(\vk \) handed to \(\op {Verify}\) can be trusted because it came from here rather than because it was simply believed.
What it does is quickly said. Each party may register one key, and only one: \(\opl {Register}\) takes the key as input — unlike \(\opl {Gen}\), which conjures one from the slot, this is a directory and not a factory — and keeps the first key it is given, sanitized against every key already on file so that no two parties ever hold the same one. The operation \(\opl {Retrieve}\) answers anyone with whatever is on file for the party they name, or nothing if no one has registered.
The fields. They are \(\Gclock \)’s, and for the same reason. The process id is a constant, \((\op {G}\op {PKI},0,0)\), so Definition 1.2 caps the system at one copy: a second directory would be a second notion of who owns which key, exactly what a PKI exists to rule out. \(\admits := \Stdpid \cup \Apid \cup \Zpid \) makes \(\op {global}(\Gpki )\) hold by the same disjunct as the clock’s, and \(\Ps \) is again the universe the directory covers rather than who has used it — registration is state, in \(\V {VK}\), not membership. One field is simpler than the clock’s: \(\uses := \emptyset \). The operations \(\op {Register}\) and \(\op {Retrieve}\) place no call at all, the key arriving with the request rather than from the slot, so there is nothing \(\Gpki \) depends on beyond the ambient machinery every functionality already has.
Two borrowed guards. \(\op {Register}\) takes one line from each of the two examples before it. The first is \(\Gclock \)’s: a caller named \(A\) or \(Z\) acting for an honest party is answered that party’s own key and changes nothing, exactly as it is answered the time rather than allowed to tick on an honest party’s behalf — an outsider may ask what is on file, not decide what goes there. At a corrupt party the check does not fire, so the call proceeds — the adversary registers on a corrupt party’s behalf as freely as it ticks one, and whatever key it submits is what the directory will show, mediation letting exactly this call through unmediated as it does for \(\Fac \)’s corrupt sends (Section 19.1). The second is \(\Fsig \)’s: the first call to succeed wins, later ones returning the key already on file rather than overwriting it, exactly as \(\op {Gen}\) never re-issues a key once one exists. Sanitizing here differs from both signature predicates in what it repairs: \(\Clean _{\vk }\) and \(\Clean _{\sigma }\) each fix a value the slot proposed; \(\Clean _{\op {reg}}\) fixes one the caller supplied, which is the more exposed position — an honest party’s own key is presumably already good, but a corrupt one’s is whatever the adversary wrote in, and the one thing a directory cannot let through is a second party claiming a key the first already holds. A good value always exists here for the same reason it does for \(\Clean _{\vk }\): \(\Keys \) is infinite and the keys excluded are exactly those a bounded run can have recorded, finitely many (footnote of Chapter 12).
Functionality \(\Gpki \)
\(\PID := (\op {G}\op {PKI},0,0)\), \(\Ps \), \(\admits := \Stdpid \cup \Apid \cup \Zpid \), \(\uses := \emptyset \), \(\pars := \none \)
\(\op {Initialize}()\):
\(\id .\op {Register}(\vk )\) from \(\id '\)
auto
\(\id .\op {Retrieve}(P)\) from \(\id '\)
\(\id .\op {Leak}()\) from \(\id '\)
\(\Clean _{\op {reg}}(\vk ; \V {VK})\):
Three remarks on the code. Registration is recorded against the party, not the caller, for the same reason ticks are: \(\opl {Guard}\) has already tied the call to \(\id .P\) by line 2, so whichever machine holds the token when \(P\) registers, the key lands on \(P\)’s own entry. There is no \(\op {Deregister}\), and none is added: a real PKI can support revocation, but a key once bound is the simplest directory there is, and revocation is a genuine addition left for elsewhere rather than a gap papered over. And \(\op {Leak}\) answers with the whole table, which is no more than \(\op {Retrieve}\) already gives out one entry at a time — the directory is public at every one of its interfaces, not only this one, so \(\op {Leak}\) tells the adversary nothing \(\op {Retrieve}\), asked enough times, would not.
Set against both examples before it, \(\Gpki \) needs less than either. No value is the simulator’s to choose out of nothing, as in \(\op {Gen}\) — the key arrives with the call — so sanitizing here repairs a caller’s input rather than a slot’s output, the one place this differs from every \(\San \) before it. And no call leaves the core at all, so there is no notification to be responsive about and no price for Chapter 9 to settle: the two properties below transfer as cheaply as a property can.