比特币使用基于椭圆曲线加密的椭圆曲线数字签名算法(ECDSA)。特定的椭圆曲线称为secp256k1,即曲线
y² = x³ + 7
在有限域 (又名伽罗瓦域),以简短描述。
椭圆曲线图y ^ 2 = x ^ 3 + 7
在平面中的椭圆曲线上的加法在几何上根据线截取曲线的位置来定义。我们不会在这里讨论几何,除了说它归结为一组涉及实数的方程。但我们并没有在实数域上去工作,而是在有限域。
我们的想法是采用由平面中的几何体激发的方程式,然后使用这些方程式来定义当您不在实数上但在不同的场上工作时的加法。在的情况下secp256k1,该字段是整数模的有限域p,其中
p = 2 256 - 2 32 - 977
这里选择p相对接近2 256。它不是小于2 256的最大素数; p和2 256之间有很多素数。其他因素也同样影响着选择p。请注意,我们不是在整数mod p本身工作,而是在一个阿贝尔组中,其加法法则由整数mod p上的椭圆曲线定义 。
(更新:这是关于secp256k1的姐妹曲线的另一篇文章,secp256r1,另一条曲线模数为256位素数,但结构不同。)
接下来,我们 在椭圆曲线上选择一个基点g。定义secp256k1 的 标准说 g是
0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
以“压缩形式”或
040x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
以“未压缩的形式”。
基点是椭圆曲线上特别选择的点,因此它是一 对数字mod p,而不是单个数字。如何从这些压缩或未压缩的表单中提取 x和 y?
该 压缩的 形式只给 x,你就应该解决 y。在 未压缩的 形式为您提供了 x 和 y。但是,这些数字是略微编码的。在压缩形式中,字符串以“o2”或“o3”开头,字符串的其余部分是 x 的十六进制表示 。将满足 y 的两个值
y² = x³ + 7 mod p
并且“o2”或“03”告诉您选择哪一个。如果压缩形式以02开头,则选择最低有效位为偶数的根。如果压缩形式从03开始,则选择其最低有效位为奇数的根。(两个根将添加到 p,而 p是奇数,因此其中一个根将是偶数,一个将是奇数。)
未压缩的表单将始终以04开头。在此之后,按照 x 和 y 连接在一起的十六进制表示形式 。
无论哪种情况,我们都有
x = 79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
和
y = 483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
我们可以使用一些Python代码验证这一点:
x = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
y = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
assert((y*y - x*x*x - 7) % p == 0)
从我们的基点 g 开始,将 kg 定义为 g 加到其自身 k 次。再次注意,这里的“加法”意义是椭圆曲线中的加法,而不是整数域 p 中的加法。椭圆曲线密码学的关键是可以有效地计算 kg,但是不能从 kg 乘积开始求解 k。您可以使用快速求幂算法计算 kg,但求解 k 需要计算离散对数。(这是ECDLP:椭圆曲线离散对数问题。)
为什么这称为“取幂”而不是“乘法”?椭圆曲线上的算术是可交换的,并且在交换(即阿贝尔)组中,组操作通常表示为加法。重复添加称为乘法。
但在一般群论中,群操作表示为乘法,并且群操作的重复应用称为取幂。使用通用术语“取幂”是常规的,即使在阿贝尔群体上,将其称为乘法更有意义。
通过取对数来撤消取幂,因此求解 k 的过程称为离散对数问题。椭圆曲线密码学的安全性取决于计算离散对数的难度。
为一组尺寸的解决离散对数问题的最佳算法 n 目前需要 O(√n) 操作。在我们的案例中,n 有多大 ?
选择基点 g 具有大的顺序,实际上它的顺序大约是2 256。具体来说, 用十六进制写的 g 的顺序是
n = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141。
这意味着我们得到大约256/2 = 128位的安全性,因为√(2 256)= 2 128。