原文在此:
https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627
1 简介
椭圆曲线配对是各种构造背后的关键密码原型之一,包括确定性阈值签名、zk-SNARKs和其他更简单形式的零知识证明。椭圆曲线对(或“双线性映射”)是对已有30年历史的椭圆曲线加密应用(包括加密和数字签名)的最新补充;配对引入了一种“加密乘法”形式,极大地扩展了基于椭圆曲线的协议的功能。 本文的目的是详细介绍椭圆曲线配对,并阐述它们工作方式的总体轮廓。
你并不会被期望在第一次阅读时就理解这里的所有内容,甚至是第十次。 这东西真的很难。但希望本文至少能让你对幕后发生的事情有一些了解。
椭圆曲线本身是一个需要理解的很不容易的主题,本文通常假设你知道它们的工作原理; 如果你知道,我在这里推荐这篇文章作为入门:
https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/
快速总结一下,椭圆曲线密码学引入被称为“点”的数学对象(这些是具有字母意义的二维点,包含(x, y)坐标),以及用于加减它们的特殊公式(如用于计算R = P + Q),你也可以将一个点乘以一个整数(如,P * n = P + P + … + P,然而如果 n 很大,存在一种快速计算它的方法),下图展示了,P+Q是如果进行计算的。
存在一个称为“无穷远点(point at infinity)”(O)的特殊点,相当于点运算中的零;对于任意点P,都有P + O = P。此外,曲线具有“阶(order)”;使得对于任意P,存在一个数字n,使得P * n = O,(当然,P * (n+1) = P、P * (7*n + 5) = P * 5等等)。还有一些公认的“生成点”G,在某种意义上可被理解为代表数字1。
配对更进一步,使得你可以检查椭圆曲线点上某些类型的更复杂的方程——例如,如果P = G * p、Q = G * q且R = G * r,那么在只有P、Q和R作为输入的情况下,可以检查p * q = r是否成立。 这看起来像是打破了椭圆曲线的基本安全保证,因为正在在仅仅知道P的时候泄漏关于p的信息,但事实证明泄漏是高度包含的(highly contained)——具体来说,决策性Diffie Hellman问题很容易,但计算Diffie Hellman 问题(在上面的例子中知道P和Q,计算R = G * p * q)和离散对数问题(从P中恢复p)在计算上仍然是不可行的(至少,如果它们以前是这样的话)。
看配对用途的第三种方法,对于我们所讨论的大多数用例来说,可能最具启发性的一种方法是,如果您将椭圆曲线点视为单向加密数字(即 encrypt(p) = p * G = P),鉴于传统的椭圆曲线数学用于检查数字上的线性约束(例如,如果P = G * p,Q = G * q 和 R = G * r,检查5 * P + 7 * Q = 11 * R,实际上是在检查5 * p + 7 * q = 11 * r),配对让你检查二次约束(例如,检查e(P, Q) * e(G, G * 5) = 1实际上是在检查p * q + 5 = 0)。上升到二次足以让我们使用确定性阈值签名、二次算术程序和所有其他好东西。
现在,我们上面介绍的这个有趣的e(P, Q)运算符是什么? 这就是配对。数学家有时也称它为双线性映射(bilinear map); 这里的“双线性”一词基本上意味着它满足约束条件:
e(P, Q + R) = e(P, Q) * e(P, R)
e(P + S, Q) = e(P, Q) * e(S, Q)
请注意,+和*可以是任意运算符;当你创建奇特的新型数学对象时,抽象代数并不关心+和*是如何定义的,只要它们以通常的方式保持一致即可,例如,a + b = b + a, (a * b) * c = a * (b * c)和(a * c) + (b * c) = (a + b) * c。
如果P、Q、R和S是简单的数字,那么进行简单配对很容易:我们可以做e(x, y) = 2^xy。然后,我们可以看到:
e(3,4+5)=2^(3*9)=2^27 e(3,4)*e(3,5)=2^(3*4)*2^(3*5)=2^12*2^25=2^27
它是双线性的!
然而,这种简单的配对不适合密码学,因为它们处理的对象是简单的整数并且太容易分析了;整数使除法、对数计算和进行各种其他计算变得容易;简单整数没有“公钥”或“单向函数”的概念。此外,通过上述配对,可以倒推——知道x,知道e(x, y),可以简单地计算一个除法和一个对数来确定y。 我们想要尽可能接近“黑匣子”的数学对象,可以在其中进行加减乘除,但除此之外别无他法。这就是椭圆曲线和椭圆曲线配对的用武之地。
事实证明,可以在椭圆曲线点上制作双线性映射——也就是说,提出一个函数e(P, Q),其中输入P和Q是椭圆曲线点,输出是所谓的F_p¹²元素(至少在我们将在此处介绍的特定情况下,具体情况因曲线的细节而异,稍后会详细介绍),但这样做背后的数学理论非常复杂。
首先,介绍素数域和扩展域。如果假设曲线方程是使用常规实数定义的,那么本文前面图片中漂亮的椭圆曲线看起来就是这样。 但是,如果真的在密码学中使用常规的实数,那么你可以使用对数“倒推”,一切都会崩溃; 此外,实际存储和表示数字所需的空间量可能会任意增长。 因此,我们改为使用在素数域中的数。
素数域由数字0、1、2…p-1组成,其中p是素数,各种运算定义如下:
a + b: (a + b) % p a * b: (a * b) % p a - b: (a - b) % p a / b: (a * b^(p-2)) % p
基本上,所有数学都是以p为模完成的(有关模块化数学的介绍,请参见此处)。除法是一种特殊情况; 通常,3/2 不是整数,这里我们只想处理整数,因此我们尝试找到满足x * 2 = 3的数字 x,其中 * 当然是指上面定义的模乘法。 多亏了费马小定理,上面显示的求幂技巧可以完成这项工作,但还有一种更快的方法,即使用扩展欧几里得算法。假设 p = 7; 这里有一些例子:
2 + 3 = 5 % 7 = 5 4 + 6 = 10 % 7 = 3 2 - 5 = -3 % 7 = 4 6 * 3 = 18 % 7 = 4 3 / 2 = (3 * 2^5) % 7 = 5 5 * 2 = 10 % 7 = 3
如果多试试这种数学,就会发现它是完全一致的并且满足所有常用的规则。上面最后两个例子展示了(a / b) * b = a; 还可以看到(a + b) + c = a + (b + c)、(a + b) * c = a * c + b * c,以及人们知道和喜爱的所有其他高中代数恒等式也适用。在现实中的椭圆曲线中,点和方程通常是在素数域中计算的。
现在,谈谈扩展域。你之前可能已经见过扩展域;在数学教科书中遇到的最常见示例是复数域,其中实数域被“扩展”了附加元素sqrt(-1) = i。基本上,扩展域的工作原理是采用现有域,然后“发明”一个新元素,并定义该元素与现有元素之间的关系(在本例中,i² + 1 = 0),确保此等式不适用于原始域中的任何数字,并查看原始域元素和刚刚创建的新元素的所有线性组合的集合。
我们也可以做素数域的扩展;例如,我们可以用i扩展我们上面描述的素数域mod 7,然后我们可以这样做:
(2 + 3i) + (4 + 2i) = 6 + 5i (5 + 2i) + 3 = 1 + 2i (6 + 2i) * 2 = 5 + 4i 4i * (2 + i) = 3 + i
最后的结果可能有点难以理解,那里情况是这样的,我们首先将乘积分解为4i * 2 + 4i * i,得到8i - 4,然后因为我们在mod 7下计算,所以最终变成 i + 3。对于除法,我们这样做:
a / b: (a * b^(p^2-2)) % p
请注意,费马小定理的指数现在是p²而不是p,不过如果我们想提高效率,我们也可以扩展扩展欧几里德算法来完成这项工作。请注意,对于该域中的任何x,x^(p² - 1) = 1,因此我们将p²-1称为“域中乘法群的阶数”。
对于实数,代数基本定理确保我们称为复数的二次扩展是“完整的”——不能进一步扩展它,因为对于任何数学关系(至少,任何由代数公式定义的数学关系)可以想出一些新元素j和现有的复数,有可能想出至少一个已经满足这种关系的复数。然而,对于质数域,我们没有这个问题,因此可以更进一步并进行三次扩展(其中一些新元素w和现有域元素之间的数学关系是三次方程,因此1、w和w²都是彼此线性独立)、高阶扩展、扩展的扩展等。椭圆曲线配对正是建立在这些类型的增压模复数之上。
对于那些有兴趣查看用代码编写所有这些操作所涉及的精确数学的人,这里实现了素数域和域扩展:
https://github.com/ethereum/py_pairing/blob/master/py_ecc/bn128/bn128_field_elements.py
现在,关于椭圆曲线配对。椭圆曲线配对(或者更确切地说,我们将在这里探讨配对的具体形式;还有其他类型的配对,尽管它们的逻辑非常相似)是映射G2 x G1 -> Gt,其中:
G1是椭圆曲线,其中点满足形式为y² = x³ + b的方程,并且两个坐标都是F_p的元素(即,它们是简单的数字,算术都是以某个素数为模完成的)
G2是一个椭圆曲线,其中点满足与G1相同的方程,除了坐标是F_p¹²的元素(即它们是我们上面讨论的增压复数;我们定义了一个新的“幻数”w,它由12次多项式定义,如w^12 - 18 * w^6 + 82 = 0)
Gt是椭圆曲线结果进入的对象类型。在我们看到的曲线中,Gt是F_p¹²(与G2中使用的相同的增压复数)
它必须满足的主要属性是双线性,在本文中意味着:
e(P, Q + R) = e(P, Q) * e(P, R)
e(P + Q, R) = e(P, R) * e(Q, R)
还有两个重要的标准:
高效的可计算性(例如,我们可以通过简单地取所有点的离散对数并将它们相乘来轻松配对,但这在计算上与首先破解椭圆曲线密码学一样困难,所以它不算数)
非退化(当然,您可以只定义 e(P, Q) = 1,但这不是特别有用的配对)
那么我们该怎么做呢?
配对函数为何起作用背后的数学原理非常棘手,涉及相当多的高级代数,甚至超出了我们目前所见,但我将提供一个大纲。 首先,我们需要定义除数的概念,基本上是在椭圆曲线点上表示函数的另一种方式。函数的除数基本上包括函数的零点和无穷大。为了了解这是什么意思,看几个例子。 固定一些点 P = (P_x, P_y),并考虑以下函数:
f(x, y) = x - P_x
除数是 [P] + [-P] - 2 * [O](方括号用于表示我们指的是点P在函数的零和无穷大集合中的存在,而不是点P本身;[P] + [Q] 与 [P + Q]不同),推理如下:
该函数在P处等于零,因为x是P_x,所以x - P_x = 0
该函数在-P处等于零,因为-P和P共享相同的x坐标
随着x趋于无穷大,函数趋于无穷大,所以我们说函数在O处等于无穷大。出于技术原因,这个无穷大需要计算两次,所以O加上-2的“多重性”(负是因为它是无穷大而不是零,2是因为这种重复计算)。
技术上的原因大致是这样的:因为曲线的方程是x³ = y² + b,为了让y²跟上x³,y比x快“1.5 倍”到达无穷大; 因此,如果线性函数仅包含x,则它表示为重数2的无穷大,但如果它包含y,则它表示为重数3的无穷大。
现在,考虑一个“线函数”:
ax + by + c = 0
其中a、b和c是经过仔细选择的,因此直线穿过点P和Q。由于椭圆曲线加法的工作原理(见顶部的图表),这也意味着它穿过-P-Q。 它随着x和y上升到无穷大,因此除数变为[P]+ [Q] + [-P-Q] - 3 * [O]。
我们知道每个“有理函数”(即仅使用有限数量+、-、* 和 / 运算作用于点坐标上定义的函数)唯一对应于某个除数,直到乘以一个常数(即,如果两个函数F和G具有相同的除数,则F = G * k对于某个常数 k)。
对于任意两个函数F和G,F * G的除数等于F的除数加上G的除数(在数学教科书中,你会看到(F * G) = (F) + (G)),例如,如果f(x, y) = P_x - x,则 (f³) = 3 * [P] + 3 * [-P] - 6 * [O];P和-P被“三次计算”,以说明f³ 在某种数学意义上,在那些点会“快三倍”的接近0的事实。
请注意,有一个定理指出,如果从函数的除数中“移除方括号”,则这些点的总和必须为O([P] + [Q] + [-P-Q] - 3 * [O]显然符合,如P + Q - P - Q - 3 * O = O),任何具有此属性的除数都是函数的除数。
现在,我们准备看看Tate配对。考虑以下函数,通过它们的除数定义:
(F_P) = n * [P] - n * [O], where n is the order of G1, ie. n * P = O for any P (F_Q) = n * [Q] - n * [O] (g) = [P + Q] - [P] - [Q] + [O]
现在,让我们看看F_P * F_Q * g^n的乘积。 除数是:
n * [P] - n * [O] + n * [Q] - n * [O] + n * [P + Q] - n * [P] - n * [Q] + n * [O]
这巧妙地简化为:
n * [P + Q] - n * [O]
请注意,此现在,我们介绍一个称为“最终求幂”步骤的过程,我们将上述函数的结果(F_P、F_Q 等)提高到z = (p12 - 1) / n的幂,其中p12 - 1是F_p12中乘法群的阶(即对于任何 x ϵ F_p12,x^(p12 - 1) = 1)。 请注意,如果你将此求幂应用于任何已经提高到n次方的结果,你将得到 p12 - 1 次方的求幂,因此结果变为1。因此,在最终求幂之后,g^n取消出来,我们得到 F_P^z * F_Q^z = F_(P + Q)^z。这对于你来说的双线性。
现在,如果你想创建一个在两个参数中都是双线性的函数,你需要进入更诡异的数学,而不是直接取一个值的F_P,你取一个除数的F_P,这就是完整的“Tate pairing”的来源。 要证明更多结果,你必须处理“线性等价”和“Weil reciprocity”等概念,而兔子洞从那里继续下去。你可以在此处找到有关这些内容的更多阅读材料。
有关Tate pairing的修改版本的实现,称为最佳Ate配对,请参见此处。该代码实现了实际计算F_P所需的Miller算法。除数的格式与上面F_P和F_Q的除数完全相同。因此,F_P * F_Q * g^n = F_(P + Q)。
请注意,像这样的配对是可能的这一事实有点喜忧参半:一方面,这意味着我们可以用配对做的所有协议都成为可能,但也意味着我们必须更加小心对待我们用的椭圆曲线。
每条椭圆曲线都有一个称为嵌入度的值;本质上,最小的k使得p^k - 1是n的倍数(其中p是用于场的素数,n是曲线阶数)。在上面的字段中,k = 12,并且在用于传统ECC的字段中(即我们不关心配对的地方),嵌入度通常非常大,以至于配对在计算上无法计算; 然而,如果我们不小心,那么我们可以生成k = 4甚至1的字段。
如果k = 1,则可以减少椭圆曲线的“离散对数”问题(本质上,恢复p只知道点 P = G * p,“破解”椭圆曲线私钥必须解决的问题) 进入与 F_p 类似的数学问题,问题变得容易得多(这称为MOV攻击);使用嵌入度为12或更高的曲线可确保这种减少不可用,或者解决配对结果的离散对数问题至少与“正常方式”从公钥恢复私钥一样困难(即,计算上不可行)。 不要担心,所有标准曲线参数都已针对此问题进行了彻底检查。
参考
https://zhuanlan.zhihu.com/p/592591301