Why not validate Curve25519 public keys could be harmful
Update: see this post for a real world protocol that is broken if Curve25519 public keys are not validated.
Update: comments on Twitter.
Most users of Curve25519 believe that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y don't have to validate public keys. I used to believe that too until I saw what could go wrong.
Recently I reviewed a protocol which could be simplified as follows
1. Alice and Bob perform cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 classic unaucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticated Diffie-Hellman dance. They obtain some shared keys at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of this step.
2. Alice uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared keys to encrypt her data, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 resulting ciphertext is broadcast over radio (Bluetooth, WIFI, etc.) Since only Bob has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared keys, nobody else could see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data.
This is more or less cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same as SSL, except that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key exchange is unaucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticated. The designers have good reasons to believe that leaving cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 protocol unaucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticated poses a low risk only. They do cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir homework, and decide to use Curve25519, a state of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 art Diffie-Hellman function. It turns out that this choice weakens cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 protocol.
If Mallory replaces Alice's and Bob's public keys with zero, which is a valid Curve25519 public key, he would be able to force cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ECDH shared value to be zero, which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encoding of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at infinity, and thus get to dictate some publicly known values as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared keys. It still requires an active man-in-cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365-middle attack to pull cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trick, after which, however, not only Mallory can decode Alice's data, but everyone too! It is also impossible for Alice and Bob to detect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 intrusion, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y still share cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same keys, and can communicate with each ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r as normal.
If you haven't figured out what is going on yourself, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 problem is that (0, 0) is a valid point on Curve25519, and has order of 2, i.e., (0, 0) + (0, 0) = cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at infinity. Curve25519 private keys are always even, thus cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared point would always be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at infinity, whose x-coordinate is encoded as zero. If none of this makes any sense, I recommend buying a copy of An Introduction to Macá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365matical Cryptography.
Run this Sage script to see it yourself:
# cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 prime
P = 2^255 - 19
# cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 finite field over P
F = GF(P)
# Curve25519, see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 paper
A = 486662
E = EllipticCurve(F, [0, A, 0, 1, 0])
# cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at infinity
INFINITY = (0, 1, 0)
# point (0, 0)
ZERO = E(0, 0)
# (0, 0) + (0, 0)
Q = ZERO + ZERO
# should output true
Q == INFINITY
OK, this sounds bad. How do I validate Curve25519 public keys? This is where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 confusion begins. Let me first quote Curve25519 official answer:
How do I validate Curve25519 public keys?
Don't. The Curve25519 function was carefully designed to allow all 32-byte strings as Diffie-Hellman public keys [...]
There are some unusual non-Diffie-Hellman elliptic-curve protocols that need to ensure ``contributory'' behavior. In those protocols, you should reject cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 32-byte strings that, in little-endian form, represent 0, 1, [...]
What is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contributory behavior? Should we care? It seems no, as long as we're using ECDH, but it recommends rejecting zero, which sounds like what we want to do to prevent cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack.
The answer is yes, you have to validate public keys if you are using a protocol that requires contributory behavior. This behavior, which sounds like a half-brocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 confused deputy, requires that none of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parties participating in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key exchange could dictate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared value. But that is allowed in our example protocol! Exactly, now you see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 root cause of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability. A better way to state cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 requirement is: you have to validate public keys if you are using a protocol that is vulnerable to key-dictating attacks.
You might think that I just made up a protocol to prove my point, but protocols requiring contributory behavior are not uncommon. For example, all versions of TLS <= 1.2 require this property, and as a result, are vulnerable to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 triple handshake attack which uses a clever trick to dictate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared value. I suspect that many homegrown protocols would be vulnerable too.
Whose fault is it? Many people, including me, consider Curve25519 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best practice when it comes to Diffie-Hellman. The problem is that, as a friend once said, in crypto cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are also cases where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best practice is wrong, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 reasons are often subtle. This is one such case. I wouldn't blame cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 designers of Curve25519. Curve25519 was designed to do one job which is to compute cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Diffie-Hellman function. It does its job well, but, like many powerful tools, it's, however, also a double-edged sword that could cause great harm when misused.
What is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 solution?
Curve25519 suggests blacklisting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 known bad public keys, but a better solution is to check cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared value and to raise exception if it is zero. You can also bind cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exchanged public keys to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared keys, i.e., instead of using H(abG) as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared keys, you should use H(aG || bG || abG). If you exchange more than public keys -- TLS exchanges nonces, certs, and ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r info -- you should include cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m too. If you are implementing Curve25519 yourself, instead of encoding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at infinity as zero, perhaps you should raise an exception. I cannot come up with any protocols which need to encode cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at infinity.
Update: comments on Twitter.
Most users of Curve25519 believe that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y don't have to validate public keys. I used to believe that too until I saw what could go wrong.
Recently I reviewed a protocol which could be simplified as follows
1. Alice and Bob perform cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 classic unaucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticated Diffie-Hellman dance. They obtain some shared keys at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of this step.
2. Alice uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared keys to encrypt her data, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 resulting ciphertext is broadcast over radio (Bluetooth, WIFI, etc.) Since only Bob has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared keys, nobody else could see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data.
This is more or less cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same as SSL, except that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key exchange is unaucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticated. The designers have good reasons to believe that leaving cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 protocol unaucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticated poses a low risk only. They do cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir homework, and decide to use Curve25519, a state of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 art Diffie-Hellman function. It turns out that this choice weakens cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 protocol.
If Mallory replaces Alice's and Bob's public keys with zero, which is a valid Curve25519 public key, he would be able to force cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ECDH shared value to be zero, which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encoding of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at infinity, and thus get to dictate some publicly known values as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared keys. It still requires an active man-in-cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365-middle attack to pull cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trick, after which, however, not only Mallory can decode Alice's data, but everyone too! It is also impossible for Alice and Bob to detect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 intrusion, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y still share cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same keys, and can communicate with each ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r as normal.
If you haven't figured out what is going on yourself, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 problem is that (0, 0) is a valid point on Curve25519, and has order of 2, i.e., (0, 0) + (0, 0) = cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at infinity. Curve25519 private keys are always even, thus cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared point would always be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at infinity, whose x-coordinate is encoded as zero. If none of this makes any sense, I recommend buying a copy of An Introduction to Macá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365matical Cryptography.
Run this Sage script to see it yourself:
# cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 prime
P = 2^255 - 19
# cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 finite field over P
F = GF(P)
# Curve25519, see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 paper
A = 486662
E = EllipticCurve(F, [0, A, 0, 1, 0])
# cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at infinity
INFINITY = (0, 1, 0)
# point (0, 0)
ZERO = E(0, 0)
# (0, 0) + (0, 0)
Q = ZERO + ZERO
# should output true
Q == INFINITY
OK, this sounds bad. How do I validate Curve25519 public keys? This is where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 confusion begins. Let me first quote Curve25519 official answer:
How do I validate Curve25519 public keys?
Don't. The Curve25519 function was carefully designed to allow all 32-byte strings as Diffie-Hellman public keys [...]
There are some unusual non-Diffie-Hellman elliptic-curve protocols that need to ensure ``contributory'' behavior. In those protocols, you should reject cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 32-byte strings that, in little-endian form, represent 0, 1, [...]
What is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contributory behavior? Should we care? It seems no, as long as we're using ECDH, but it recommends rejecting zero, which sounds like what we want to do to prevent cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack.
The answer is yes, you have to validate public keys if you are using a protocol that requires contributory behavior. This behavior, which sounds like a half-brocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 confused deputy, requires that none of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parties participating in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key exchange could dictate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared value. But that is allowed in our example protocol! Exactly, now you see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 root cause of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability. A better way to state cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 requirement is: you have to validate public keys if you are using a protocol that is vulnerable to key-dictating attacks.
You might think that I just made up a protocol to prove my point, but protocols requiring contributory behavior are not uncommon. For example, all versions of TLS <= 1.2 require this property, and as a result, are vulnerable to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 triple handshake attack which uses a clever trick to dictate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared value. I suspect that many homegrown protocols would be vulnerable too.
Whose fault is it? Many people, including me, consider Curve25519 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best practice when it comes to Diffie-Hellman. The problem is that, as a friend once said, in crypto cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are also cases where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best practice is wrong, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 reasons are often subtle. This is one such case. I wouldn't blame cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 designers of Curve25519. Curve25519 was designed to do one job which is to compute cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Diffie-Hellman function. It does its job well, but, like many powerful tools, it's, however, also a double-edged sword that could cause great harm when misused.
What is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 solution?
Curve25519 suggests blacklisting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 known bad public keys, but a better solution is to check cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared value and to raise exception if it is zero. You can also bind cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exchanged public keys to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared keys, i.e., instead of using H(abG) as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared keys, you should use H(aG || bG || abG). If you exchange more than public keys -- TLS exchanges nonces, certs, and ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r info -- you should include cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m too. If you are implementing Curve25519 yourself, instead of encoding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at infinity as zero, perhaps you should raise an exception. I cannot come up with any protocols which need to encode cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at infinity.
Comments