When a transaction is made with monero there is a 'key image' in the transaction info. what is this exactly? is it like the diffie-hellman exchange to create the one time addresses?
4 Answers
Monero are always sent to the one-time destination (public key) P. In the CN whitepaper, the corresponding private key is referred to as x.
When you're spending, you're combining your P with a couple of other ones in a ring signature and signing with the x. Only one of the Ps will be spent, but the ring signatures hide which one. In other words, the signature is verified by all of the Ps, and it looks like any of their corresponding private keys could have signed the transaction, thus obfuscating the sender. But how do we know you're not double-spending? We need a way to prove that the private key used to sign was not used before, without revealing which one it is. That is where the key image comes in:
I = xHp(P)
Let's also take a look at how the one-time key-pair is derived:
P=xG
Since I is a one-way function of x this means that:
- Nobody can recover the public key from the key image and identify the signer;
- The signer cannot make two signatures with different I’s and the same x which in effect means you can spend your P only once.
- 20,004
- 3
- 49
- 105
The key image is an alternate public key computed on a second base point, specifically Hp(P), instead of G. It is required in traceable ring signature construction to ensure multiple signatures with the same real key are linked (and thus rejected by the Monero protocol).
- 2,472
- 12
- 14
The layman's way to look at what a key image is would be that it allows the Monero network to quickly confirm whether an output as been spent or not. In other words, the key image is a necessary component of Monero's opaque blockchain ecosystem, because it allows for the prevention of double-spends.
For more information on this concept, please refer to this question and answer:
What is Monero's mechanism for defending against a double-spend attack?
- 5,515
- 21
- 42
I created a small repository with basic monero functions:
def calc_key_image(a: bytes, b: bytes, R: bytes, i:int) -> bytes:
"""Calculate key image for input
Args:
a: bytes; Private view key
b: bytes; Private spend key
R: bytes; Transaction public key (rG) of refferenced output transaction. Stored in field extra[1:33]).hex().
i: int; output index of refferenced output
Returns:
Key image : string
"""
# x = H_s(aR) + b
aR = ed25519.encodepoint(ed25519.scalarmult(ed25519.decodepoint(R), ed25519.decodeint(a)))
aR = ed25519.encodepoint(ed25519.scalarmult(ed25519.decodepoint(aR), 8 )) # There is a mathematical reason for this...
aR += bytes([i])
Hs = sc_reduce32(keccak_256(aR).digest())
x = int.from_bytes(Hs, byteorder='little') + int.from_bytes(b, byteorder='little')
x = x % ed25519.l
x = x.to_bytes(32, 'little')
Hp = hashToPointCN(ed25519.publickey(x))
return ed25519.encodepoint(ed25519.scalarmult(Hp, ed25519.decodeint(x)))
- 1
- 1