英文:
Why different Wireguard private keys resulting in the same public key?
问题
我发现不同的Wireguard私钥可能会得到相同的公钥。
在“不同的密钥”中,我指的是在计算公钥的curve25519过程中,私钥的第一个字节的最后四位被忽略。
如果有人能解释这种奇怪的行为,我将不胜感激。
示例:
❯ echo "Mp4S2elbVWEo2xzGtefU8eIccYMkX3XD8y3yNGeOMXE=" | wg pubkey
YG8wJtIMuqTmO7l4OMDBkT516y8NigBilaqZt3fDdCU=
❯ echo "MJ4S2elbVWEo2xzGtefU8eIccYMkX3XD8y3yNGeOMXE=" | wg pubkey
YG8wJtIMuqTmO7l4OMDBkT516y8NigBilaqZt3fDdCU=
❯ echo "MZ4S2elbVWEo2xzGtefU8eIccYMkX3XD8y3yNGeOMXE=" | wg pubkey
YG8wJtIMuqTmO7l4OMDBkT516y8NigBilaqZt3fDdCU=
❯ echo "M54S2elbVWEo2xzGtefU8eIccYMkX3XD8y3yNGeOMXE=" | wg pubkey
YG8wJtIMuqTmO7l4OMDBkT516y8NigBilaqZt3fDdCU=
英文:
I discovered that different Wireguard private keys could result in the same public key.
Under "different keys" I mean four last bits in a first byte of a private key are ignored during curve25519 calculation for a public one.
I will appreciate if someone can explain this strange(?) behaviour.
Example:
❯ echo "Mp4S2elbVWEo2xzGtefU8eIccYMkX3XD8y3yNGeOMXE=" | wg pubkey
YG8wJtIMuqTmO7l4OMDBkT516y8NigBilaqZt3fDdCU=
❯ echo "MJ4S2elbVWEo2xzGtefU8eIccYMkX3XD8y3yNGeOMXE=" | wg pubkey
YG8wJtIMuqTmO7l4OMDBkT516y8NigBilaqZt3fDdCU=
❯ echo "MZ4S2elbVWEo2xzGtefU8eIccYMkX3XD8y3yNGeOMXE=" | wg pubkey
YG8wJtIMuqTmO7l4OMDBkT516y8NigBilaqZt3fDdCU=
❯ echo "M54S2elbVWEo2xzGtefU8eIccYMkX3XD8y3yNGeOMXE=" | wg pubkey
YG8wJtIMuqTmO7l4OMDBkT516y8NigBilaqZt3fDdCU=
答案1
得分: 6
这是由于Curve25519的夹紧操作。你可以在Neil Madden的博客文章中详细了解它:
https://neilmadden.blog/2020/05/28/whats-the-curve25519-clamping-all-about/
你正在使用一个256位的私钥(32字节)。这是一个完全随机的数。出于安全原因,并不是所有可能的数都适合作为curve25519私钥的标量值。
- 值需要在2的251次方和2的252次方减1之间
- 最低的3位需要为零
以下是对一个256位随机数执行这些步骤的夹紧函数:
// 清除最低的3位
t[0] &= 248;
// 清除最高的1位(确保t < 2^252)
t[31] &= 127;
// 设置次高位(确保t >= 2^251)
t[31] |= 64;
在导出公钥之前执行这些步骤。
即使你有一个256位的密钥,实际上只有2的251次方个不同的密钥。
因此,不仅第一个字节的最后4位的值无关紧要,最后一个字节的前两位的值也无关紧要。
英文:
This is due to Curve25519 clamping. You can read all about it in this blog article by Neil Madden:
https://neilmadden.blog/2020/05/28/whats-the-curve25519-clamping-all-about/
You are using a 256-bit private key (32 bytes). This is a completely random number. Not all of these possible numbers are suitable as scalar values for a curve25519 private key, for good security-related reasons.
- the value needs to be between 2<sup>251</sup> and 2<sup>252</sup>-1
- the lower 3 bits need to be zero
What clamping function on a 256-bit random number performs these steps:
// clear least-significant 3 bits
t[0] &= 248;
// clear most significant 1 bit (ensure t < 2^252)
t[31] &= 127;
// set the second-most significant bit (ensures t >= 2^251)
t[31] |= 64;
It performs these steps before deriving the public key.
Even though you have a 256-bit key, there are only 2<sup>251</sup> distinct keys.
So, not only does the value of four last bits in the first byte not matter, but the value of the two first bits in the last byte don't matter either.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论