写在前面
本篇Blog为了方便理解和阅读,修改了原文的一些符号和记法
Abstract
d-MSM算法主要用于计算下列等式,其中$a_1,\dots,a_d$为$d$个$l$比特标量,$P_1,\dots,P_d$为$d$个椭圆曲线$E$上的点,$[a_1]P_1$表示点的标量乘法
$$ [a_1]P_1 + \cdots + [a_d]P_d $$
这一计算在密码学算法中很常见,包括但不限于EdDSA、ECDH,但是朴素的计算方法开销很大,之前有桶方法或者Karabina算法来加速计算
之前的Blog也介绍过MSM,这里跳过
这篇paper提出了对上述两类方法的优化,第一种方法在内存可以保存$2^d-1$个点时非常有效,第二种方法则用于处理超过$2^d-1$个点时的情况
Notation
- $a,b,x\in \Z$:标量
- $C$:矩阵
- $[a,b]$:由整数$a,b$划定的整数区间
- $\mathrm{HW}(x)$:$x$的汉明重量
- $C^T$:矩阵$C$的转置矩阵
- $p$:素数
- $\mathbb K$:由$p$确定的有限域
- $E$:定义在$\mathbb K$上的椭圆曲线
- $\mathcal O$:无穷远点
- $\mathrm A$:$E$上的加法运算
- $\mathrm D$:$E$上的二倍点乘法
Case of d=2
这里先看$d=2$的情况,也就是两个点的标量乘相加$[a_1]P_1+[a_2]P_2$,有很多种方式可以处理,一一介绍
Shamir Trick
Shamir Trick$[2,3]$可以处理此类情况,具体如下
首先将$a_1,a_2$表示为二进制形式,如下
$$ (a_1)_2 = (b^{(1)}_{l-1}b^{(1)}_{l-2}\dots b^{(1)}_1b^{(1)}_0)\\ (a_2)_2 = (b^{(2)}_{l-1}b^{(2)}_{l-2}\dots b^{(2)}_1b^{(2)}_0) $$
然后将这些比特组成一个矩阵$C$
$$ C=\begin{pmatrix}b_{l-1}^{(1)}&\cdots&b_1^{(1)}&b_0^{(1)}\\b_{l-1}^{(2)}&\cdots&b_1^{(2)}&b_0^{(2)}\end{pmatrix} $$
这样一来,我们要计算的式$[a_1]P_1+[a_2]P_2$可以转换为下面这个形式
$$ \begin{aligned} \begin{aligned}[\alpha_1]P_1+[\alpha_2]P_2\end{aligned}& =\quad(P_1,P_2)C\begin{pmatrix}2^{l-1}\\\vdots\\2^1\\2^0\end{pmatrix} \\ &=\quad[2^{l-1}]([b_{l-1}^{(1)}]P_1+[b_{l-1}^{(2)}]P_2)+\cdots+[2^1]([b_1^{(1)}]P_1 \\ & +[b_1^{(2)}]P_2)+[2^0]([b_0^{(1)}]P_1+[b_0^{(2)}]P_2) \end{aligned} $$
其实就是拆分成$l$个点加法$([b^{(1)}_i]P_1+[b^{(2)}_i]P_2)$,然后再将加法结果乘上对应的2的幂$2^i$
分析一下上述方法需要的加法次数,可以看出主要取决于$a_1,a_2$的联合汉明重量(Joint Hamming Weight,JHW),也即矩阵$C$中非零元素的数量
由于$a_1,a_2$可以视为长度为$l$比特的随机标量,因此从统计的角度来看,联合汉明重量$\mathrm{JHW}(a_1,a_2)\approx \frac{3}{4}l$
注意到整个算法包含$l$个步骤,每一步中需要一次二倍点运算($[2^i]$部分),且至少需要1次群加法运算(如果当前步骤的两个比特$(b_i^{(1)},b^{(2)}_i)$任意一个不为0,则需要一次额外的群加法)
综上,算法整体需要的计算开销为$\frac{3}{4}l\cdot \mathrm A+(l-1)\cdot \mathrm D$(需要预计算$G = P_1+P_2$)
对于标量$a$的表示方式,如果二进制表示中1的数量太多的话(汉明重量太大),可以通过特殊方式降低汉明重量,比如下面这样,其中$\bar 1 = -1$
$$ a=(11100011111011)_2=(100\bar{1}00100000\bar{1}0\bar{1}) $$
如果$\mathrm {HW}(a_1)\approx \mathrm{HW}(a_2)\approx \frac{l}{3}$,则$\mathrm{JHW}(a_1,a_2)\approx\frac{5}{9}$,但是这里引入了负数,因此预计算的点需要多一个:$H = P_1 - P_2$,此时算法的计算开销可以降低为$\frac{5}{9}l\cdot \mathrm A+l\cdot \mathrm D$
Bernsteins's method(DJB)
方法来自$[4]$
考虑蒙哥马利椭圆曲线方程
$$ y^2 = x^3+ax^2+x $$
蒙哥马利曲线有一个特点,可以直接通过相加两个点的横坐标来实现点加法($P_1 + P_2$)或减法($P_2 - P_1$)
基于这个特性,Bernstein设计了一个快速计算$[a_1]P_1+[a_2]P_2$的方法,每个滋补粥只需要一次倍点和两次点加法运算,但是这个方法限制了$P_1,P_2$必须为蒙哥马利曲线上的点
这个方法需要引入三个中间变量$T_1,T_2,T_3$,这三个变量在初始化时分别被设置为$T_1 = \mathcal O,T_2 = P_1,T_3 = P_2$,,之后在每个计算步骤都会更新$T_1,T_2,T_3$
下面这个图给出了一个如何计算$13P_1+17P_2$的例子(这里没有用到$(1,-1)$这个中间值)
对于长度为$l$比特的标量,Bernstein的方法需要计算$2l$次点加法和$l$次倍点
Case of d>2
如果有三个或以上的点,此时又该如何完成计算
Hankerson等人提出了一种交织的方法来计算,具体可以看$[5-6]$两篇Refs
另外还有一种桶方法,思想有点类似于桶排序,之前的Blog$[7]$有介绍过
This Paper's methods
本文给出了两种计算方法来计算MSM,假设内存中可以保存至多$2^M - 1$个点,这两种方法分别用于处理$d\leq M$($d$不太大)和$d< M$($d$比较大)时的情况
Multidimensional Shamir's trick
第一种方法,多维Shamir trick,用于处理$d$不太大的情况
还是和原版的Shamir trick一样,将$d$个标量拆分为二进制表示,然后组合成矩阵,如下
$$ C=\begin{pmatrix}b_{l-1}^{(1)}&\cdots&b_1^{(1)}&b_0^{(1)}\\b_{l-1}^{(2)}&\cdots&b_1^{(2)}&b_0^{(2)}\\\vdots&\vdots&\ddots&\vdots\\b_{l-1}^{(d)}&\cdots&b_1^{(d)}&b_0^{(d)}\end{pmatrix} $$
然后将待计算的$d$个点拼成一个行向量$P$,并构造一个由2的幂组成的列向量$S$,如下
$$ P=\begin{pmatrix}P_1&P_2&\cdots&P_d\end{pmatrix}\\S=\begin{pmatrix}2^{l-1}\\\vdots\\2^1\\2^0\end{pmatrix} $$
然后MSM的计算过程就可以转化为$P\cdot C\cdot S$,如下
$$ \begin{aligned} \begin{aligned}[\alpha_1]P_1+[\alpha_2]P_2+\cdots+[\alpha_d]P_d\end{aligned}& =P\cdot C\cdot S \\ &=P\begin{pmatrix}b_{l-1}^{(1)}&\cdots&b_1^{(1)}&b_0^{(1)}\\b_{l-1}^{(2)}&\cdots&b_1^{(2)}&b_0^{(2)}\\\vdots&\vdots&\ddots&\vdots\\b_{l-1}^{(d)}&\cdots&b_1^{(d)}&b_0^{(d)}\end{pmatrix}\begin{pmatrix}2^{l-1}\\\vdots\\2^1\\2^0\end{pmatrix} \\ &=[2^{l-1}]([b_{l-1}^{(d)}]P_d+\cdots+[b_{l-1}^{(2)}]P_2+[b_{l-1}^{(1)}]P_1) \\ &+[2^{l-2}]([b_{l-2}^{(d)}]P_d+\cdots+[b_{l-2}^{(2)}]P_2+[b_{l-2}^{(1)}]P_1) \\ &+[2^1]([b_1^{(d)}]P_d+\cdots+[b_1^{(2)}]P_2+[b_1^{(1)}]P_1) \\ &+[2^0]([b_0^{(d)}]P_d+\cdots+[b_0^{(2)}]P_2+[b_0^{(1)}]P_1) \end{aligned} $$
和原版的Shamir trick,需要一些预计算,但是这里不只是预计算一个点这么简单了,需要预计算一个表$T$,表项由所有的$\sum^d_{i = 1,b^{(i)}_j\neq 0} P_i$组成,$T$长下面这样
$$ \begin{aligned} T[0] &= \mathcal O \\ T[1] &= P_1 \\ T[2]&=P_{2} \\ T[3]&=P_{1}+P_{2} \\ T[4]&=P_{3}, \\ T[5]&=P_{1}+P_{3} \\ T[6]&=P_{2}+P_{3} \\ &\vdots \\ T[2^d-1]&=P_{1}+P_{2}+\cdots+P_{d} \end{aligned} $$
这样MSM的计算过程就可以转化为下面这样
$$ [a_1]P_1+[a_2]P_2+\cdots+[a_d]P_d=[2^{l-1}]T[x_{l-1}]+[2^{l-2}]T[x_{l-2}]+\cdots+[2^1]T[x_1]+[2^0]T[x_0]. $$
其中$x_j,T[x_j]$如下($j\in [0,l-1]$)
$$ \begin{aligned}x_j=\bigoplus_{i=1}^d(b_j^{(i)}<<(i-1))\end{aligned} \\T[x_j] = \sum_{i=1,b_j^{(i)} \neq 0}^{d} P_i $$
这里分析一下复杂度,首先保存这个表$T$需要$2^d-1$的存储空间,然后预计算表$T$的这些表项需要$2^d-d-1$次点加法
对于每一次计算$j\in [0,l-1]$,如果当前步骤中的比特$b^{(i)}_j(1\leq i\leq d)$有至少一个非零,则本步骤的计算需要一次倍点和一次点加法(和上一步骤的运算相加),算法主体(不考虑预计算)需要的倍点运算次数为$l$次,需要的点加法运算与$d$个标量的联合汉明距离相关,即
$$ l\cdot \mathrm{JHW}(a_1,\dots,a_d) \approx l \cdot (1-\frac{1}{2^d}) $$
这里原文给了个简单的例子,用上面的方法计算$13P_1+17P_2+21P_3$
首先将三个标量表示为5比特二进制数(也即$l = 5$),然后排列成矩阵$C$,如下
$$ C= \begin{pmatrix}0&1&1&0&1\\1&0&0&0&1\\1&0&1&0&1\end{pmatrix} $$
然后计算表$T$如下
$$ T = \{\mathcal O,P_1,P_2,P_1+P_2,P_3,P_1+P_3,P_2+P_3,P_1+P_2+P_3\} $$
然后$13P_1+17P_2+21P_3$就可以转化为下面这样
$$ \begin{aligned} [13]P_1+[17]P_2+[21]P_3& =P\cdot C\cdot S \\ &=\begin{pmatrix}P_1,P_2,P_3\end{pmatrix}\begin{pmatrix}0&1&1&0&1\\1&0&0&0&1\\1&0&1&0&1\end{pmatrix}\begin{pmatrix}2^4\\2^3\\2^2\\2^1\\2^0\end{pmatrix} \\ &=\begin{pmatrix}P_1,P_2,P_3\end{pmatrix}\begin{pmatrix}2^3+2^2+2^0\\2^4+2^0\\2^4+2^2+2^0\end{pmatrix} \\ &=[2^4]T[6]+[2^3]T[1]+[2^2]T[5]+[2^1]T[0]+[2^0]T[7] \end{aligned} $$
预计算需要4次点加法,算法主体需要5次倍点和4次点加法,内存开销为7个点
Multidimensional Double and Add
注意到有些算法中的$d$往往很大(比如zkSNARK中的多项式往往可以到$d = 2^{22}$),此时没有任何服务器可以存储这么多点$2^{2^{22}} = 2^{4,194,304}$,不能再按照上述方法实现,因此需要一种新的方法来处理此类情况
首先还是和之前的方法,将每一个标量$a_i$表示为二进制形式,并和之前一样计算$x_j$
这里与上一节的区别在于,如果$x_j\neq 0$,则按照下列方式计算$T[x_j]$
$$ T[x_j]\leftarrow 2\cdot T[x_j] + \sum_{i=1,b_j^{(i)} \neq 0}^{d} P_i $$
这个方法的原理是这样:$x_j = 0$的概率与$\forall i \in [i,d],b^{(i)}_j = 0$的概率相等,当$d$足够大时,此时$x_j = 0$的概率接近于可忽略(具体是$\frac{1}{2^d}$,当$d = 2^{22}$时,$\mathrm{Pr}[x_j = 0] = 2^{-4,194,304}$)
这个方法的每一次计算步骤的计算开销为1次倍点运算(上式的$2\cdot T[x_j]$部分),$\mathrm{HW}(x_j) - 1$次加法(计算上式的求和部分),以及一次加法(将上式的两个计算结果加起来)
综上,总的计算开销为$l$次倍点计算和$\sum_{j = 0}^{l-1} \mathrm{HW}(x_j)$次点加法,如果标量$a_i$满足均匀分布,则$\mathrm{HW}(x_j)\approx \frac{d}{2}$,因此计算开销为
$$ \frac{d}{2}\cdot l\cdot \mathrm A +l\cdot D $$
这里还是给一个例子,计算$17P_1+25P_2+28P_3+12P_4$
这里按照上面的计算思路,有$x_0 = 3,x_1 = 0,x_2 = 12,x_3 = 14,x_4 = 7$,因此计算过程如下
$$ \begin{aligned} [a_{1}]P_{1}+[a_{2}]P_{2}+[a_{3}]P_{3}+[a_{4}]P_{4}& =[17]P_1+[25]P_2+[28]P_3+[12]P_4 \\ &=[16](P_1+P_2+P_3)+[8](P_2+P_3+P_4 \\ &+[4](P_3+P_4)+[2]\mathcal O+(P_1+P_2) \\ &=[2^4]([1]P_1+[1]P_2+[1]P_3+[0]P_4) \\ &+[2^3]([0]P_1+[1]P_2+[1]P_3+[1]P_4) \\ &+[2^2]([0]P_1+[0]P_2+[1]P_3+[1]P_4) \\ &+[2^1]([0]P_1+[0]P_2+[0]P_3+[0]P_4) \\ &+[2^0]([1]P_1+[1]P_2+[0]P_3+[0]P_4). \end{aligned} $$
然后计算开销主要分析汉明重量$\mathrm{HW}(x_i)$,不难计算得到$\mathrm{HW}(x_0) = 2,\mathrm{HW}(x_2) = 2,\mathrm{HW}(x_3) = 3,\mathrm{HW}(x_4) = 3$,因此计算开销为5次倍点运算和10次点加法,需要的存储开销为4个点
安全性分析与效率分析
TODO,可以参考原文$[1]$
References
$[1] On Computing the Multidimensional Scalar Multiplication on Elliptic Curves (iacr.org)
$[2]$ Addition chains of vectors
$[3]$ A public key cryptosystem and a signature scheme based on discrete logarithms
$[4]$ Differential addition chains
$[5]$ Elliptic Curve Cryptography
$[6]$ wnaf*, an efficient left-to-right signed digit recoding algorithm
$[7]$ MSM算法 - 三两老友杂的小岛 (snowolf0620.xyz)