$$ \newcommand \KeyDilution {\mathrm{KeyDilution}} \newcommand \Batch {\mathrm{Batch}} \newcommand \Offset {\mathrm{Offset}} $$
Algorand’s Two-level Ephemeral Signature Scheme for Authentication
For a player with their participation keys registered on the Ledger (and hosted on an Algorand node), a set of ephemeral sub-keys is created.
An ephemeral sub-key is a key pair that produces one-time signature for messages. It MUST be deleted after use to ensure forward security. Algorand’s ephemeral subkeys use Ed25519 public-key signature system.
For further details, refer to the Cryptography primitives specification.
Algorand uses a two-level ephemeral signature scheme. Instead of signing voting messages directly, Algorand accounts use their registered voting keys to sign an intermediate ephemeral sub-key.
This intermediate ephemeral sub-key signs a batch of leaf-level ephemeral sub-keys. Hence, each intermediate ephemeral sub-key is associated with a batch number (\( \Batch \)), and each leaf ephemeral sub-key is associated with both a batch number (of its parent key) and an offset (\( \Offset \), denotes its offset within a \( \Batch \)). An agreement voting message is signed hierarchically:
Voting Keys Root Key
└── Batch Sub-Key
└── Leaf Sub-Key
└── Agreement Voting Message
Further details on this process in the One-time Signature subsection.
Each leaf-level ephemeral sub-key is used for voting on a single agreement round, and will be deleted afterward. Once a batch of leaf-level ephemeral sub-keys run out, a new batch is generated. Algorand allows users to set the number of leaf-level ephemeral sub-key per batch, \( \KeyDilution \).
The default \( \KeyDilution \) value is \( 10{,}000 \).
An Algorand account can change its \( \KeyDilution \) in the participation keys registration.
For further details about the structure of a participation keys registration (
keyreg
) transaction, refer to the Ledger specification.
The following diagram shows the tree structure of the voting signature scheme:
flowchart TD root["One-Time Signature container"] --> p0["Batch Signer 1"] root --> p1["Batch Signer 2"] root --> pDot["..."] root --> pN["Batch Signer N"] p0 --> v0["Batch 1 Key 1"] p0 --> v1["Batch 1 Key 2"] p0 --> vDot["..."] p0 --> vN["Batch 1 Key N"]