The Double-Spend Problem in Identity

A public key is a very simple kind of identity. If I give you a public key and later sign a message with the corresponding private key, you can verify that I was the one who signed it. No account database, certificate authority, or blockchain is required.

This is what people mean when they say public keys are self-certifying. The identifier contains the information needed to verify it.

There is one obvious downside: if I lose the private key, or someone steals it, the identity is compromised forever. There is no way to recover it without changing the identifier itself.

Most identity systems therefore want something more flexible. They want a stable identifier that can stay the same while the keys behind it change. Maybe I lost my phone. Maybe I want a separate key for my laptop. Maybe an employee left a company. Maybe a board elected new members.

This seems like a small addition. It is not.

Stable identity is mutable state

Suppose we create a stable identifier called SID. Initially it points to pk1:

SID -> pk1

Later I want to rotate to pk2, so I sign a statement with sk1 saying that pk2 is now the new key:

SID -> pk1 -> pk2

The signature proves something useful: whoever held sk1 authorized this transition.

But it does not prove that this was the only transition authorized by sk1.

The same key could also authorize pk3:

SID -> pk1 -> pk2
        └───> pk3

Both branches are cryptographically valid. This is not a failure of signatures. Signatures are doing exactly what they are supposed to do. They prove that sk1 authorized both statements.

The problem is that an identity system wants these statements to mean something stronger. It wants one of them to be the canonical successor and the other one to be invalid.

This is very similar to the double-spend problem in money. A Bitcoin transaction is not just a valid signature spending a coin. The network also needs to agree on whether that coin was spent before. Likewise, a key rotation is not just a valid signature naming a new key. A new peer needs to know whether the old authority has already been used to establish a different future.

The historical fork is the real problem

The obvious attack is that someone steals the currently active sk1 and creates two different rotations. But there is a more subtle version.

Imagine that pk1 was rotated away from years ago. An attacker later obtains the old sk1. They can now construct an entire alternative history:

SID -> pk1 -> attacker-pk3 -> attacker-pk4 -> ...

Every signature in this history can be valid. Nothing in a normal signature says when it was created. A new peer receiving this history from an arbitrary P2P peer cannot know whether it was authored years ago, when pk1 was actually current, or produced yesterday using a leaked old key.

Peers that already knew the pk2 branch can keep it. This is sometimes called trust on first use. It is useful, but it does not solve the actual discovery problem. A new peer still has no trustless way to decide which branch is correct.

Hash chains and sequence numbers do not solve this either. They prove that each branch is internally consistent. They make forks visible once you have received both branches. They cannot tell you that a branch you have not received exists.

This is the double-spend problem in identity: a historical authority can be spent twice to create incompatible futures, and a new observer cannot tell which future is canonical.

Why this matters most for organizations

For an individual identity, this attack normally requires an old key to be stolen, lost, or retained insecurely. That is a serious risk, but it is hopefully uncommon if the root key is backed up offline and never kept on a normal device.

For organizations it is much worse. Historical authority keys are naturally held by people who may later become adversarial: former board members, founders, employees, investors, multisig participants, custodians, or members of a political organization that splits in two.

Consider an organization controlled by an old board. At some point it transitions to a new board:

old board -> new board

The old board can also create a different transition:

old board -> rival board

No theft is needed. The old board already had legitimate authority in the historical state. A new counterparty that only sees one signed history cannot know whether it represents the actual succession or an alternative history created by former stakeholders.

This is not an esoteric identity-theory problem. It applies to who controls a treasury, who can publish a software release, who can issue credentials, who owns a project namespace, or who may enter into agreements for an organization.

Consider a 2-of-3 threshold. Initially the organization is controlled by Alice, Bob, and Carol. Over time it rotates first to Bob, Carol, and David, and later to Carol, David, and Eve:

A, B, C -> B, C, D -> C, D, E

Now imagine that Alice and Bob have been removed for years and become hostile to the current organization. They still hold their old keys. They can use the original 2-of-3 configuration to create a completely different history:

A, B, C -> A, B, F

From that point they can continue rotating among keys they control, shutting out Carol, David, and Eve. A new peer that receives this history cannot know that Alice and Bob created it after they had already been removed. It only sees a valid 2-of-3 transition from a historical configuration.

Strictly speaking, at least one signer has equivocated: the real first transition and the rival first transition are both 2-of-3 quorums from A, B, C, so they must overlap. But that does not make the attack less relevant. The security property comes from assuming that the overlapping signer remembers the real transition and permanently refuses to sign a conflicting one. This is a real and useful BFT-style assumption, but it is an assumption about governance, key custody, persistent state, and honest behavior. Dynamic membership changes make this more complicated still, because the threshold rules must remain safe across every old and new configuration.

This is why I think the double-spend problem in identity is particularly important for organizational identity. Organizational succession is adversarial by default often enough that we should not hide this behind a signed history and call it resolved.

The normal answer is to trust someone

Most real-world identity systems already solve this problem by introducing an authority that says what is current, or what time an event occurred.

Centralized account systems have a database. If the database says a user changed their password or recovery key, that is the current state. Certificate authorities have revocation and status systems. Trusted timestamp authorities sign statements about time.

DNS is another useful example. A domain name is stable while its DNS keys can rotate, but DNS does not solve this through pure peer-to-peer signed history. It has a hierarchy of registries, registrars, parent zones, and authoritative servers. DNSSEC adds signatures and a chain of trust, while normal key rollover carefully overlaps old and new keys to account for caches and propagation delays. The system has clear places where authority lives.

This introduces trust and operational dependencies. A registrar can make mistakes. An account provider can censor you. A timestamp service can disappear. But it also gives a new user an answer to a question that signatures alone cannot answer: which state is current?

What pure P2P can do

If we want to use only self-certifying data, there is no cryptographic fact that lets us recover the intent behind two valid conflicting histories. We can only choose a policy.

We can keep both heads. This is honest, and it can work for applications where conflict is acceptable. But it gives up the idea that an identity has one current authority.

We can merge the histories. This works for some monotonic data. For example, once I have learned a device key is revoked, I can keep that fact forever and merge it with any other known revocations. It does not work for a state transition that means "exactly one of these two keys is current".

We can choose a deterministic winner, perhaps the branch with the lowest hash. Then every peer that eventually receives the same data will converge. But the rule is arbitrary, a party that can create alternatives may be able to influence it, and an attacker can withhold a losing or winning branch until it is convenient to reveal it.

Or we can declare the whole identity invalid when a fork is discovered. This is the conservative answer if having one canonical head is mandatory. It also means that anyone who obtains historical authority can destroy the identity by manufacturing a conflicting branch.

There is a useful pure P2P design for individual identity nonetheless. Make the root public key itself the stable identity. Generate the root key from a seed phrase, back up that seed offline on paper or more durable physical media, and remove it from normal devices after initial setup. Use the root only for recovery and to delegate scoped device keys. Everyday operations use separate device keys. This does not solve the problem cryptographically. A stolen root seed is still catastrophic, and a lost seed is still terminal. It does however make root theft much less likely in practice, while keeping ordinary identity operations fully peer-to-peer.

It is also tempting to use expiring device delegations here. But expiry requires a shared concept of time. A fully P2P hash chain gives us order within a branch, not a globally comparable clock. Revocation has the same availability problem: a peer that has not received a revocation cannot know that it exists.

KERI and blockchain anchored identity histories

There are several attempts to get more of the benefits of mutable identity without simply relying on a central database.

KERI uses a mechanism called pre-rotation. A key event commits to the next key configuration before that configuration is revealed. For a verifier that already knows this exact event, compromise of the active key cannot extend it with an arbitrary successor: a valid rotation must use the separately held key that was committed in advance.

This yields a narrow operational recovery benefit, but only if the committed next private key is protected separately from the active key. The normal idea is that the active key is exposed for ordinary signing, while the unrevealed next key is kept in a more protected reserve. If both keys live in the same wallet, seed, or compromised device, an attacker will obtain both and pre-rotation buys almost nothing.

More importantly, it does not solve the problem in this article. The compromised current key can sign an alternative version of the event where it became current, using the same predecessor but committing to attacker-controlled next keys. A new peer can be shown this alternative history and cannot know which key-state event was really published. Pre-rotation therefore gives no trustless canonical-history guarantee to a newly joining peer. KERI can use witnesses to receipt events, making publication more accountable and available under a threshold assumption, but the canonical branch comes from that (trusted) witness assumption, not from pre-rotation itself.

It also does not give an isolated new peer a globally canonical branch. A holder of the legitimately committed next key can still sign conflicting event bodies. Different witnesses or verifiers can observe different valid versions first. Witnesses make this behavior detectable and accountable under a stated fault model, but they do not make the problem disappear.

Sidetree, ION, and the Ceramic protocol / 3ID model (which I architected) take another approach. They keep identity operations offchain for scalability, but anchor batches of them to a blockchain. The blockchain provides a shared order, while P2P networks distribute the larger operation data. You get high throughput and cheap P2P distribution, while still having a way to establish a chronological reference identifiers.

However, this is not quite the same as having a blockchain where each identity is protected from double-spends. ION documents a problem called the late publishing attack. An attacker can anchor an earlier conflicting operation, withhold the offchain data needed to validate it, publish a later operation that everyone believes is the head, and finally reveal the earlier operation. Once it is revealed, the resolver switches to the earlier anchored branch. The Sidetree authors claim that this is ok because "the DID owner decides to update the state of their DID". However, as we've seen above with organizational identities, this is clearly not good enough.

The important lesson is that ordering and availability are different things. A timestamped hash or reference is not enough if the data it refers to can be withheld. A system that needs finality must define when an operation becomes publicly available and effective, not merely when someone privately committed to it.

Narrow finality using blockchains

We could just decide to store the entire identity in a state machine on a blockchain instead, and make an RPC call to a blockchain node every time you want to look up the state of the identity. This completely solves the problem of identity double-spend, but adds overhead. Especially if you want peers to be fully trustless and not have to rely on a third party hosted blockchain node.

There is a useful middle ground however. Keep ordinary data, device keys, delegation, and P2P synchronization offchain. Only use a blockchain for the rare transitions where we need globally exclusive finality: root rotation, disaster recovery, or organizational succession.

Ethereum is a natural example. A small contract can store something like:

SID -> current_key, rotation_nonce

Every rotation is validated against the contract's current state and atomically advances it. Once pk1 has been replaced by pk2 in finalized Ethereum state, sk1 cannot submit an alternative successor. The contract does not merely check whether sk1 made a valid signature. It checks whether sk1 is still the authority in the one canonical state machine.

There are two ways to use this.

Strict proof-carrying rotations

Each P2P rotation carries proof that it was finalized by the Ethereum contract. A stateless Ethereum client such as Colibri can verify this proof without trusting a normal RPC provider. A new peer can therefore fetch the identity history from any P2P peer and reject an alternative historical branch immediately.

This is the strongest design. It does, however, require a blockchain transaction for every root transition, finality latency, public metadata, and proof/header verification.

Lazy conflict escalation

Alternatively, clients can normally use P2P identity data without looking up Ethereum at all. If they receive two conflicting branches, they then check Ethereum state and resolve the conflict (this time also preferably with a stateless client).

This makes the blockchain a much narrower dependency in the normal case. It is reasonable if a client can treat the P2P branch as provisional and correct it later. It is not appropriate if accepting the wrong branch immediately grants irreversible authority or transfers value.

Importantly, this approach only saves normal-case reads. The legitimate root transition must still be written to Ethereum when it happens. If two valid signed histories are first presented to the contract after a conflict is discovered, the contract has no way to infer which one was originally intended. So it doesn't save any transaction cost during a key rotation, but it can improve performance in the normal case where there is no conflict.

The finality choice

The point is not that every identity must be on Ethereum. That would be expensive, unnecessarily public, and a poor fit for many applications.

For individual identity, a pure P2P design with an immutable offline root and delegated device keys can be a very reasonable tradeoff. Key theft is uncommon enough that accepting the residual disaster-recovery risk may be preferable to making every identity transition depend on a blockchain.

For organizational identity, I think the answer is different. Former stakeholders naturally retain historical authority and may have adversarial incentives. Threshold governance makes this harder, but does not remove the need to trust its fault and succession assumptions. If a new peer needs to trustlessly verify who canonically controls an organization, an externally ordered finality mechanism is needed.

This is the actual tradeoff space:

  • Pure P2P gives us self-certifying data, local control, and eventual convergence.
  • Trusted services give us a current-state answer in exchange for trust and dependency.
  • Blockchains give us a shared, verifiable state machine in exchange for cost, latency, and public coordination.

Signatures prove who authorized a history. They do not prove which valid history a new peer should treat as current.


See all posts