从Mentgomery到CIOS
1.重新回忆Montgomery算法
Montgomery算法的核心思想是将正常数域上的取模操作,变换到适合于计算机操作的redix-2数域上,再进行取模操作。
step1:数域转换,设原始数据为a,b,映射到Montgomery域
A = M o n t ( a , ( R 2 m o d N ) , N ) = a ∗ R 2 ∗ R − 1 m o d N = a ∗ R m o d N B = M o n t ( b , ( R 2 m o d N ) , N ) = b ∗ R 2 ∗ R − 1 m o d N = b ∗ R m o d N A=Mont(a,(R^2modN),N)=a*R^2*R^{-1}modN=a*RmodN\\ B=Mont(b,(R^2modN),N)=b*R^2*R^{-1}modN=b*RmodN A=Mont(a,(R2modN),N)=a∗R2∗R−1modN=a∗RmodNB=Mont(b,(R2modN),N)=b∗R2∗R−1modN=b∗RmodN
step2:进行Montgomery算法
/*
Input:A,B,N,R
Output:A*B*R^(-1)modN
*/
Mont(A,B,N,R):
1. N' = -N^(-1)modR;
2. T = A*B;
3. M = T*N'modR;
4. T = T + M*N;
5. T = T/R;
6 if(T>N)return T-N;//约减
7. else return T;
step3:改进M
上面的计算是要一次性计算出M,这样做的缺点是,M可能会很大,大到难以存储,那么假设在b进制下,就可以将M看作(假设M在2进制下有s位):
T
=
(
t
s
−
1
,
t
s
−
2
,
.
.
.
t
0
)
2
M
=
(
M
s
−
1
,
M
s
−
2
,
.
.
.
M
0
)
2
M
=
∑
M
i
∗
2
i
(
注
:
i
∈
[
0
,
s
−
1
]
)
T=(t_{s-1},t_{s-2},...t_0)_2\\ M=(M_{s-1},M_{s-2},...M_0)_2\\ M = ∑M_{i}*2^i(注:i∈[0,s-1])
T=(ts−1,ts−2,...t0)2M=(Ms−1,Ms−2,...M0)2M=∑Mi∗2i(注:i∈[0,s−1])
那么上述第三第四步骤就可以进行合并:
f
o
r
(
i
=
0
;
i
<
=
s
−
1
;
i
+
+
)
{
m
i
=
t
i
N
′
m
o
d
R
;
T
=
T
+
m
i
2
i
N
;
}
for(i=0;i<=s-1;i++)\\ \{ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ m_i = t_iN'modR;\\ T = T + m_i2^iN;\\ \}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
for(i=0;i<=s−1;i++){ mi=tiN′modR;T=T+mi2iN;}
step4:代换N’
与M同样,N’也存在过宽而导致无法存储的问题,下面规定,一次存储的位宽w=32bit。使用下式替换调N’:
令
R
=
2
w
;
N
0
′
=
N
′
m
o
d
R
或
者
N
0
′
=
−
N
0
−
1
m
o
d
R
令R=2^w;\\ N_0^{'} = N'modR或者N_0^{'}=-N_0^{-1}modR\\
令R=2w;N0′=N′modR或者N0′=−N0−1modR
则Montgomery算法可以变换为:
N
0
′
=
N
′
m
o
d
R
T
=
A
∗
B
f
o
r
(
i
=
0
;
i
<
=
s
−
1
;
i
+
+
)
{
m
i
=
t
i
N
0
′
m
o
d
R
;
T
=
T
+
m
i
2
i
N
;
}
T
=
T
/
R
;
i
f
(
T
>
N
)
r
e
t
u
r
n
T
−
N
;
e
l
s
e
r
e
t
u
r
n
T
;
N_0^{'}=N'modR\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ T=A*B\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ for(i=0;i<=s-1;i++)\\ \{ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ m_i = t_iN_0'modR;\\ T = T + m_i2^iN;\\ \} \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ T = T/R;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ if(T>N)return \ T-N;\ \ \ \ \ \ \\ else \ return T;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\
N0′=N′modR T=A∗B for(i=0;i<=s−1;i++){ mi=tiN0′modR;T=T+mi2iN;} T=T/R; if(T>N)return T−N; else returnT;
一致性说明:可以把上述式子中for循环部分展开:
m
0
=
t
0
N
0
′
m
o
d
R
m
1
=
t
1
N
0
′
m
o
d
R
m
2
=
t
2
N
0
′
m
o
d
R
.
.
.
m
s
−
1
=
t
s
−
1
N
0
′
m
o
d
R
T
0
=
T
+
m
0
∗
2
0
N
=
(
t
0
N
0
′
m
o
d
R
)
2
0
N
=
(
N
0
′
N
t
0
2
0
)
m
o
d
R
T
1
=
T
+
(
N
0
′
N
t
0
2
0
)
m
o
d
R
+
(
N
0
′
N
t
1
2
1
)
m
o
d
R
.
.
.
T
s
−
1
=
T
+
(
N
0
′
N
t
0
2
0
)
m
o
d
R
+
.
.
.
+
(
N
0
′
N
t
s
−
1
2
s
−
1
)
m
o
d
R
=
T
+
N
0
′
N
∑
(
t
i
2
i
)
(
m
o
d
R
)
m_0=t_0N_0'modR\\ m_1=t_1N_0'modR\\ m_2=t_2N_0'modR\\ ...\\ m_{s-1}=t_{s-1}N_0'modR\\ T_0 = T + m_0*2^0N=(t_0N_0'modR)2^0N=(N_0'Nt_02^0)modR\\ T_1 =T +(N_0'Nt_02^0)modR + (N_0'Nt_12^1)modR\\ ...\\ T_{s-1}=T +(N_0'Nt_02^0)modR+...+(N_0'Nt_{s-1}2^{s-1})modR\\ =T +N_0'N∑(t_i2^i)(modR)
m0=t0N0′modRm1=t1N0′modRm2=t2N0′modR...ms−1=ts−1N0′modRT0=T+m0∗20N=(t0N0′modR)20N=(N0′Nt020)modRT1=T+(N0′Nt020)modR+(N0′Nt121)modR...Ts−1=T+(N0′Nt020)modR+...+(N0′Nts−12s−1)modR=T+N0′N∑(ti2i)(modR)
带入:
N
0
′
=
N
′
m
o
d
R
T
s
−
1
=
T
+
N
0
′
N
∑
(
t
i
2
i
)
(
m
o
d
R
)
=
T
+
N
′
N
(
m
o
d
R
)
∑
(
t
i
2
i
)
(
m
o
d
R
)
=
T
+
N
′
N
∑
(
t
i
2
i
)
(
m
o
d
R
)
又
T
=
∑
(
t
i
2
i
)
原
式
=
T
+
N
(
T
∗
N
′
m
o
d
R
)
=
T
+
M
N
可
见
与
"
1
"
中
M
o
n
t
(
A
,
B
,
N
,
R
)
步
骤
完
全
一
致
N_0^{'} = N'modR\\ T_{s-1} =T +N_0'N∑(t_i2^i)(modR)\\ =T +N'N(modR)∑(t_i2^i)(modR)\\ =T +N'N∑(t_i2^i)(modR)\\ 又T = ∑(t_i2^i)\\ 原式=T+N(T*N'modR)=T+MN\\ 可见与"1"中Mont(A,B,N,R)步骤完全一致
N0′=N′modRTs−1=T+N0′N∑(ti2i)(modR)=T+N′N(modR)∑(ti2i)(modR)=T+N′N∑(ti2i)(modR)又T=∑(ti2i)原式=T+N(T∗N′modR)=T+MN可见与"1"中Mont(A,B,N,R)步骤完全一致
step5:代换T
上面步骤都需要实现计算T,同样的T=AB也是一个很大的数,同样可以将AB的过程进行拆分,对A*B的拆分比较容易:
KaTeX parse error: Undefined control sequence: \ at position 248: … \ \ \ \ \ \ \ \̲ ̲
最终算法更新为:
N
0
′
=
N
′
m
o
d
R
;
T
=
0
;
/
/
初
值
0
f
o
r
(
i
=
0
;
i
<
=
s
−
1
;
i
+
+
)
{
T
=
T
+
a
i
b
i
B
;
m
i
=
t
i
N
0
′
m
o
d
R
;
T
=
T
+
m
i
2
i
N
;
}
T
=
T
/
R
;
i
f
(
T
>
N
)
r
e
t
u
r
n
T
−
N
;
e
l
s
e
r
e
t
u
r
n
T
;
N_0^{'}=N'modR;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ T=0;//初值0\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ for(i=0;i<=s-1;i++)\\ \{ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ T = T + a_ib^iB;\\ m_i = t_iN_0'modR;\\ T = T + m_i2^iN;\\ \} \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ T = T/R;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ if(T>N)return \ T-N;\ \ \ \ \ \ \\ else \ return T;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\
N0′=N′modR; T=0;//初值0 for(i=0;i<=s−1;i++){ T=T+aibiB;mi=tiN0′modR;T=T+mi2iN;} T=T/R; if(T>N)return T−N; else returnT;
2.从Mentgomery到CIOS
按照上述五个步骤,可以对Mentgomery算法进行改正,那么建立在上述五个改进步骤之上,产生了CIOS算法:
输入:A,B,n,n'[0]
输出:T = A*B*R^(-1)(modN)
T = 0;
(C,S) = 0;
for(i=0;i<=s-1;i++)
{
C = 0;
for (j=0;j<=s-1;j++)
{
(C,S) = t[j] + a[j]*b[i] + C;
t[j] = S;
}
(C,S) = t[s] + C;
t[s] = S;
t[s+1] = C ;
C = 0;
m = t[0]*n'[0] mod W;//W = 2^w
for (j=0;j<=s-1;j++)
{
(C,S) = t[j] + m*n[j] + C;
t[j] = S;
}
(C,S) = t[s] + C;
t[s] = S;
t[s+1] = t[s+1] + C;
for (j=0;j<=s;j++)//※※
t[j] = t[j+1];
}
T = {ts,t(s-1),...,t1,t0};
if(T>N)return T-N;//约减
else return T;
//(version2020.6.3:这里还是存在问题,T和N仍可能很占空间,不可能一次做完)
下面逐块分析CIOS算法,首先明确两个字符C和S:
C
:
C
a
r
r
y
,
进
位
字
符
,
表
示
上
次
计
算
的
进
位
值
。
S
:
S
u
m
,
表
示
本
次
加
法
计
算
的
结
果
。
C:Carry,进位字符,表示上次计算的进位值。\\ S:Sum,表示本次加法计算的结果。
C:Carry,进位字符,表示上次计算的进位值。S:Sum,表示本次加法计算的结果。
上面提到的CIOS算法需要遵循下面假设:
1.每次操作使用的变量位宽w = 32bit。
2.每个数组单元:例如t[i],指的是当前操作的32bit存储空间,换句话来说"//※※"处的for循环,会导致t[0]被t[1]覆盖,
等价于对T = {ts,t(s-1),...,t1,t0};一次性右移32bit,
等价于T/W;其中W = 2^w
由于"//※※"在内循环j中,而外循环(即变量i的循环)会执行S次,就相当于T会被移动S个W次,即右移2^(sw)个bit,而恰好R = 2^(sw)。完成了T/R的操作。
计算A*B:
for(i=0;i<=s-1;i++)
{
C = 0;
for (j=0;j<=s-1;j++)
{
(C,S) = t[j] + a[j]*b[i] + C;
t[j] = S;
}
(C,S) = t[s] + C;
t[s] = S;
t[s+1] = C ;
}
如上式,如果删去后面的一部分,就可以明显的看出内循环中,第一个for循环是用来计算A*B,即完成Step5所对应的修正。
计算M修正:
C = 0;
m = t[0]*n'[0] mod W;//W = 2^w
for (j=0;j<=s-1;j++)
{
(C,S) = t[j] + m*n[j] + C;
t[j] = S;
}
(C,S) = t[s] + C;
t[s] = S;
t[s+1] = t[s+1] + C;
for (j=0;j<=s;j++)//※※
t[j] = t[j+1];
我将最后一个循环也放在了这个里面,主要是因为,想说明在做最后一个for循环(实质上式在计算T>>32或者说T/(2^32))时,是如何能保证整除的。
定
理
:
假
设
n
和
r
的
g
c
d
(
n
,
r
)
=
1
。
且
满
足
r
∗
r
−
1
−
n
∗
n
′
=
1
n
′
=
−
n
−
1
m
o
d
r
,
则
对
所
有
整
数
t
,
当
m
=
t
∗
n
′
m
o
d
r
时
(
t
+
m
∗
n
)
/
r
是
一
个
整
数
,
且
满
足
(
t
+
m
∗
n
)
/
r
≡
t
∗
r
−
1
m
o
d
n
。
证
明
:
因
为
r
∗
r
−
1
−
n
∗
n
′
=
1
,
则
(
t
+
m
∗
n
)
/
r
=
(
t
+
t
∗
n
′
∗
n
)
/
r
=
(
t
+
t
∗
(
r
∗
r
−
1
−
1
)
)
/
r
=
t
∗
r
−
1
m
o
d
n
定理:假设n和r的gcd(n,r)=1。且满足\\ r*r^{-1}-n*n'=1\\ n'=-n^{-1}modr,\\ 则对所有整数t,当m=t*n'modr时\\ (t+m*n)/r是一个整数,且满足(t+m*n)/r≡t*r^{-1}modn。\\ \\\ \\ 证明:因为r*r^{-1}-n*n'=1,则\\ (t+m*n)/r=(t+t*n'*n)/r=(t+t*(r*r^{-1}-1))/r=t*r^{-1}modn
定理:假设n和r的gcd(n,r)=1。且满足r∗r−1−n∗n′=1n′=−n−1modr,则对所有整数t,当m=t∗n′modr时(t+m∗n)/r是一个整数,且满足(t+m∗n)/r≡t∗r−1modn。 证明:因为r∗r−1−n∗n′=1,则(t+m∗n)/r=(t+t∗n′∗n)/r=(t+t∗(r∗r−1−1))/r=t∗r−1modn
则可以看到,每次内循环当j=0时,均有:
(C,S) = t[0] + m*n[0] + C;
==>带入m
==>t[0] + t[0]*n'[0]*n[0] + C;
==>将t[0]+C整体看做定理中所述的整数t,而定理中的r = 2^w = 2^32
==>显然t[0]是可以被2^32整出的
又由于外循环(i循环的存在),最终每次增加的C会被加入到T中去,进而完成了:
4. T = T + M*N;
5. T = T/R;
这两个步骤。