Key image
L'impronta che un output lascia quando viene speso, esattamente una volta
La key image (immagine della chiave) I = x·Hp(P), dove P è la chiave monouso dell'output e x la sua chiave privata. Per un dato output la key image è sempre la stessa, ma non rivela di quale output si tratti. La rete memorizza tutte le key image e rifiuta una transazione con una key image ripetuta.
Il problema della doppia spesa
In Bitcoin le doppie spese sono facili da individuare: ogni input punta dritto all'output che spende, e un nodo ricorda l'output come speso (l'insieme UTXO). In Monero un input punta a 16 output, e quale sia quello reale è sconosciuto. Quindi "contrassegnare l'output speso" è impossibile. Serve un modo per contrassegnare una spesa senza rivelare cosa è stato speso.
La soluzione
Perché funziona:
- Deterministica.
xePsono fissi per un output, quindiIè unica. Spendere di nuovo l'output significa pubblicare la stessaI. - Non collegabile. Per verificare che
Icorrisponda aPservex: un estraneo vede due punti "casuali"Hp(P)eIe non può stabilire il legame (un problema di Diffie–Hellman). - Non falsificabile. La linkable ring signature dimostra che
Iè stata calcolata con lo stessoxdi una delle chiavi del ring.
Perché Hp(P) e non semplicemente G? In quel caso I = x·G = P: la key image sarebbe uguale alla chiave pubblica dell'output e la spesa sarebbe subito visibile. Hp dà un punto di cui nessuno conosce il logaritmo: una "seconda base" unica per ogni output.
Il controllo del sottogruppo: il bug del 2017
Ed25519 ha 8 volte più punti del sottogruppo di G. Aggiungendo a I un punto di ordine piccolo T (con 8·T = 0) si ottiene un punto diverso I' = I + T, e in certe condizioni la ring signature risultava comunque valida. Un output: fino a 8 key image diverse, fino a 8 spese. Nel 2017 questo bug è stato trovato nel codice originale di CryptoNote; Monero lo ha corretto prima che venisse sfruttato, mentre Bytecoin è stato colpito.
La correzione: il nodo verifica che l·I = 0, cioè che I stia nel sottogruppo corretto.
Key image e wallet in sola visualizzazione
Per sapere se un tuo output è stato speso, il wallet calcola la sua key image e la cerca sulla blockchain. Per farlo serve x = Hs(8aR ‖ i) + b, cioè la spend key. Per questo un wallet in sola visualizzazione non vede le spese e mostra un saldo gonfiato. Il rimedio è esportare le key image dal wallet completo. Carrot aggiunge una chiave dedicata a questo scopo.
Key image in FCMP++
In FCMP++ la key image resta: L = x·Hp(O). Cambia il modo in cui si dimostra il suo legame con l'output: invece di un ring, una prova di appartenenza all'albero di tutti gli output. Una conseguenza importante: tutte le key image già pubblicate nelle transazioni RingCT mantengono il loro significato, quindi un vecchio output non può essere speso una seconda volta dopo il passaggio.