I’ve been working on a concept I’ve called uniquonym.
To explain it in terms of what it does (rather than how):
- Every natural person has one true identity number (per state they are associated with), endorsed by their state, with a private key that proves they own it. States have a monopoly on endorsing natural people (this might not appeal to people who entirely oppose statism) - and it is unfortunately necessary to trust them not to create armies of fake identities. These identity endorsements have an expiry, but can be re-issued (even before expiry) under the same ID number by the state (but note: this doesn’t allow uniquonym theft).
- People can create an identity (called a uniquonym) in a namespace, which is valid until expiry. In this process, they create a key pair, and hold the private key. However, each true cryptographic identity can only create one unexpired identity per namespace. There is no limit to the number of namespaces. Unless the knowledge is shared / leaked through another channel, no one except the person who created it (even the government) can tie a uniqunym in one namespace to a uniqunym for the same person in another namespace (and, as implied by the above, can’t tie a uniqunym to a natural person). Uniquonyms do expose the state that endorsed the underlying true identity.
- When a uniquonym expires and is reissued, and the true identity endorsement also expired and is reissued, the new uniquonym can’t automatically be tied to the old one, even within the namespace - but the owner of them could prove continuity by signing a protocol message with the old and new private keys.
- If someone’s true identity private key is lost / an identity against their ID number is fraudulently issued, then they will just need to wait until the true identity expires before they can start issuing uniquonyms. This is a trade-off between the alternative of letting governments be able to tie uniquonyms to true identity numbers - I personally think the privacy is more important, and process and safeguards could mitigate the impact.
In terms of how it works, at a sketch:
- Lets assume firstly that getting governments to act like a CA and issue certificates tying a person to a unique ID is a solved problem (it’s not, more on the workaround to transition to this later) - and so the individual has a private key, and a government-signed certificate linking the public key to a unique ID. Assume the unique ID itself is just an identifying number and not, by itself, sensitive (e.g. proof of knowledge of the unique ID doesn’t prove who you are).
- For each state, there will exist a Merkle tree, and a block chain of timestamped messages that update the Merkle tree. Each leaf node contains a state-issued certificate. Valid operations in update messages are to remove expired certificates (if no such message is in the block chain with a recent timestamp), or to add a certificate for an ID that doesn’t exist in the tree. This Merkle tree represents the valid set of true identities, and the blockchain represents how the tree evolves over time.
- Where P is the private key for a true identity, and there is some well-known cryptographic hash H, and where
||
denotes concatenation, a uniquonym is constructed asU = H(magic || P || sep || len(namespace) || namespace)
. magic and sep are well-known strings. - Before a user can use a uniquonym U, they must submit, in the protocol built on uniquonyms, a zero knowledge proof that there exists a path through a recent version of the true identity Merkle tree to a certificate (the root hash of the tree version used is a public parameter of the proof), and that the public key on that certificate corresponds to private key P, and that
U = H(magic || P || sep || len(namespace) || namespace)
, and that there exists a string SPpn such thatSPpn = H(magic2 || P || pn)
, and the expiry on the certificate is less than the expiry of the uniquonym (a public parameter). pn is a public key half of a keypair(Pn, pn)
(generated by the owner of the uniquonym), and a public parameter of the ZKP. - The user uses
Pn
to sign messages from uniquonymU
, and everyone in the protocol can verify them using the true identity block chain, and the message with the proof (which ties the public key pn to the message, and the proof to a particular version of the Merkle tree).
This scheme could be a primitive for building many desirable things:
- Protocols that are more resistant to DoS, with rate limits per uniquonym.
- Abuse-resistant pseudonymous messaging - spammers and others breaking rules can be blocked / banned by users / moderators, and can’t just immediately come back. Having several pseudonyms in the same forum is sometimes a feature - a middle ground is to include a random number between 0 and
n-1
in the namespace (excluding numbers used by the user already), so users can have up ton
identities, and once they are all banned there is no coming back until the true identity private key expires and is replaced. - Universal Basic Income baked into cryptocurrencies.
- Voting (including on acceptance of blocks into blockchains) on an approximately one-person-one-vote basis. This contrasts to proof-of-work (one vote per unit of energy wasted) and proof-of-stake (effectively one dollar, one vote).
The biggest problem with adopting this scheme is government cooperation before it is popular. Some governments might just provide certificates, but most don’t.
Fortunately, many states already offer TLS-based services (e.g. over HTTPS) that include a unique ID. Unfortunately, stock TLS by itself is not friendly to obtaining proof for offline protocols; it works by key exchange, and then using a shared secret to encrypt - so the client can encrypt whatever they like and say it came from the server. TLS-N would provide TLS non-repudiation, but it requires implementation on the server. TLSNotary allows for interactive verification through multi-party computing - but you either need to have a trusted third party, or have interactive involvement of everyone who cares about the authenticity of the TLS transcript.
If we accept the need for a trusted third party other than the government, there is a question of how we can build trust in this party. One option would be to put trust in hardware manufacturers to attest secure enclaves or TPMs. For TPMs, I discovered TPM2.0 doesn’t provide sufficient primitives to implement TLS 1.3. For secure enclaves, every major CPU vendor has major problems with voltage glitching or similar exploit approaches that undermine their security - so this approach isn’t viable.
Another approach is to make a well-known public cloud providers the trusted third party. This is something that I would rather avoid if there was a better alternative - after all, many of these cloud providers are widely recognised as major threats to privacy. However, the terms provided by the cloud provider wing (GCP) by companies like Google are far more favourable to users than the terms for their normal services (e.g. they at least enter into a binding agreement not to use or disclose the information except to provide the cloud service or where required by law). The cloud provider would have the same access as a government - they could fake TLS transcripts to mint fake public-key / identity associations (creating fake people or DoSing real ones), and could also collect confidential information from the TLS transcript (e.g. government authorisation tokens) to subsequently impersonate a real user to their government. However, they wouldn’t be able to link a true identity number to a uniquonym. As a transitional step to build demand for state cooperation with true self-sovereign true identity, I think it is a pragmatic choice.
The question is then whether there is a way to implement this TLS transcript attestation on an existing cloud provider using their existing services (i.e. without bespoke cooperation from the cloud provider), and without neccessitating an additional trust relationship on the person using the services.
It turns out this is possible on GCP. Google provides an option for their compute called “Confidential Computing”, where they provide a Google-signed certificate for the attestation key of a virtualised TPM (vTPM). Signing keys can be created on the vTPM, with flags that guarantee they are created on the vTPM, and policies that limit the TPM2 Policy Configuration Registers (PCRs) allowed to sign with the key - and the vTPM can create an attestation signed by the attestation key about the signing public key, the flags and the policy. The PCRs are hashes of events - Google’s virtual firmware updates a PCR with a hash of the bootloader, and the bootloader can be compiled (changing its hash) to update PCRs with the hash of all commands run and images loaded - including the Linux kernel and an initramfs image. The initramfs image includes all the binaries run (starting from the init script). In summary, an attestation, which can non-interactively be verified, is created which proves (assuming no Google trickery) that a signing key can only be used by known code running.
I have built tls-attestproxy, which has a proxy component to run on GCP which accepts a websocket connection from a client, and accepts plaintext in, and TLS connection bytes in, and writes TLS connection bytes out, and plaintext bytes out. The client verifies the signing key attestation from the proxy, and establishes a secret key with the proxy (using ECDH, with the proxy public key signed). Subsequent messages are protected with AES-GCM so the client has confidence only a real proxy running known code can see the plaintext (short of Google trickery). The client makes the TLS connection to the TLS server, and forwards it over the websocket to the proxy. The proxy verifies the certificate of the TLS server against its internal list of trusted CAs (included in the initramfs, so impacting the hash), and also sends the Certificate Transparency ID back to the client (and includes it in the transcript hash). Once the connection closes cleanly, the proxy provides a signed hash of the plaintext transcript back over the WebSocket. The client records the entire transcript. The client serialises out the signing key attestation, transcript attestation, and transcript - which can then be used non-interactively to verify the transcript.
What do people think of the concept? Can you see any problems with it? Does this open up any new application possibilities for you?