2020暑假-Crypto
公钥算法的基本数论知识
欧几里得算法 \(\gcd\)
-
\[\gcd(r_0,r_1)=\gcd(r_0-r_1,r_1) \]
- c++实现
int gcd(int a,int b) { return b?gcd(b,a%b):a; }
- python实现
def gcd(a,b) : while b!=0 : if a<b: a,b=b,a if b==0 : break a%=b return a
扩展欧几里得算法 exgcd
- 可以用来计算模逆元
- 除了用来计算\(\gcd(r_0,r_1)\),还能计算以下形式的线性组合\[\gcd(r_0,r_1)=s\cdot r_0+t\cdot r_1 \\ 丢番图方程(Diophantine\quad equation) \]计算s和t两个系数,执行标准欧几里得算法,但将每轮迭代种的余数\(r_{i}\)表示为以下形式的线性组合:\[r_{i}=s_{i}r_0+t_{i}r_1 \]如果这个过程成功了,则最后一轮迭代对应的等式为:\[r_1=\gcd(r_0,r_1)=s_{l}r_0+t_{l}r_1=sr_0+tr_1 \]范例请看《深入浅出密码学——常用加密技术原理与应用》P151
假设当前迭代对应的索引为i,则前两轮迭代种计算的值为:\[r_{i-2}=[s_{i-2}]r_0+[t_{i-2}]r_1\\ r_{i-1}=[s_{i-1}]r_0+[t_{i-1}]r_1 \]在当前第i轮迭代种,首先需要从\(r_{i-1}\)与\(r_{i-1}\)中计算商\(q_{i-1}\)和新余数\(r_{i}\):\[r_{i-2}=q_{i-1}\cdot r_{i-1}+r_{i} \]这个等式也可以写成:\[r_{i}=r_{i-2}-q_{i-1}\cdot r_{i-1} \]用前两个式子替换一下,得到:\[r_{i}=(s_{i-1}r_0+t_{i-2}r_1)-q_{i-1}(s_{i-1}r_0+t_{i-1}r_1) \]将这些项重新排序,就可得到想要的结果:\[r_i=[s_{i-2}-q_{i-1}s_{i-1}]r_0+[t_{i-2}-q_{i-1}t_{i-1}]r_1\\ r_i=[s_i]r_0+[t_i]r_1 \]上面的等式直观的给出了计算\(s_i\)和\(t_i\)的递归公式即\[s_i=s_{i-2}-q_{i-1}s_{i-1}\\ t_i=t_{i-2}-q_{i-1}t_{i-1} \]这个递归表达式只对\(i \geqq 2\)的索引值有效,这些初始值为\[s_0=1,s_1=0,t_0=0,t_1=1 \] - 伪代码
输入:正整数r0,r1,且r0>r1
输出:gcd(r0,r1),以及满足gcd(r0,r1)=s*r0+t*r1的s和t
初始化:s[0]=1,t[0]=0,s[1]=0,t[1]=1,i=1
算法:
do
i=i+1
r[0]=r[i-2]mod r[i-1]
q[i-1]=(r[i-1]-r[i])/r[i-1]
s[i]=s[i-2]-q[i-1]*s[i-1]
t[i]=t[i-2]-q[i-1]*t[i-1]
while r[i]!=0
return
gcd(r[0],r[1])=r[i-1]
s=s[i-1]
t=t[i-1]
- c++实现
int exgcd(int a, int b, int &x, int &y) { //x,y初始为任意值,最后变为一组特解
if(b == 0) { //对应最终情况,a=gcd(a,b),b=0,此时x=1,y为任意数
x = 1;
y = 0;
return a;
}
int r = exgcd(b, a % b, x, y); //先递归到最终情况,再反推出初始情况
int t = x; x = y; y = t - a / b * y;
return r; //gcd(a,b)
}
- python实现
def exgcd(a, b, x, y):
if b==0:
x=1
y=0
returna
r=exgcd(b,a%b,x,y)
t=x
x=y
y=t-a//b*y
return r
-
exgcd(EEA)求逆元
假设我们想计算\(r_1 \bmod r_0\)的逆元,其中\(r_1<r_0\)。只有在\(\gcd(r_0,r_1)=1\)的情况下逆元才存在。因此,使用EEA求逆元
\[s\cdot r_0+t\cdot r_1=1\\ s\cdot0+t\cdot r_1 \equiv1 \bmod r_0 \\ r_1 \cdot t \equiv 1 \bmod r_0\\ \Rightarrow t=r_1^{-1}\bmod r_0 \]因此如果需要计算逆元\(a_1^{-1}\bmod m\),直接输入参数为m和a的EEA即可,计算得到的输出值t即为逆元
-
计算逆元python
def EX_GCD(a,b,arr): #扩展欧几里得
if b == 0:
arr[0] = 1
arr[1] = 0
return a
g = EX_GCD(b, a % b, arr)
t = arr[0]
arr[0] = arr[1]
arr[1] = t - int(a / b) * arr[1]
return g
def ModReverse(a,n): #ax=1(mod n) 求a模n的乘法逆x
arr = [0,1,]
gcd = EX_GCD(a,n,arr)
if gcd == 1:
return (arr[0] % n + n) % n
else:
return -1
欧拉函数
- \(\mathbb{Z}_m\)内与\(m\)互素的整数个数可以表示为\(\Phi(m)\)
- 定理:
假设m可以因式分解为一下数的连乘\[m=P_1^{e_1}\cdot P_2^{e_2} \cdots P_n^{e_n} \]则有\[\Phi(m)=\prod_{i=1}^N (P_i^{e_i}-P_i^{e_{i-1}}) \]
费马小定理
- 假定\(a\)为一个整数,\(p\)为一个素数,则:\[a^p \equiv a(\bmod \quad p) \]也可以表示为一下形式:\[a^{p-1} \equiv 1(\bmod p) \]对有限域\(GF(p)\)内所有整数元素都成立
- 计算逆元\[a^{p-2} \cdot a \equiv1(\bmod p)\\ \Rightarrow a^{-1}\bmod a^{p-2}(\bmod p) \]
欧拉定理
- 将费马小定理的模数推广到任何整数模,即可得欧拉定理
- 假设\(a\)和\(m\)都是整数,且\(\gcd(a,m)=1\),则:\[a^{\Phi(m)}\equiv1(\bmod m) \]
- 费马小定理是欧拉定理的特殊形式:\[P为素数,\Phi(P)=(P^1-P^0)=P-1\\ \Rightarrow a^{\Phi(P)}=a^{P-1}\equiv1(\bmod P) \]
群
定义
群G,有时记为$ {G,* } $,是定义了一个二元运算的非空集合,这个二元运算可表示为 \(*\),G中的每一个序偶\((a,b)\)通过运算生成G中的元素\((a*b)\),并满足以下公理:
- 封闭性:如果a和b都属于G,则\(a*b\)也属于G。
- 结合律:对于G中任意a,b,c,都有\((a*b)*c=a*(b*c)\)成立。
- 单位元:G中存在一个元素e,对于G中任意元素a,都有\(a*e=e*a=a\)。
- 逆元: G中都存在一个元素\(a’\),使得下式成立:\(a*a’=a’*a=e\)
如果一个群的元素是有限的,则该群称为有限群,并且群的阶就等于群中元素的个数。否则,称该群为无限群。
一个群如果还满足以下条件,则称为交换群: - 交换律:对于G中任意的元素a,b,都有\(a*b=b*a\)成立。
(来自段段ppt)
- 二元运算:设\(s\)为集合,函数\(f:s\times s\rightarrow s\)称为\(s\)上的二元运算或代数运算(用*表示),满足以下性质
- 可计算性:s中任何元素都可以进行这种运算;
- 单值性:运算结果唯一;
- 封闭性:s中任何两个元素运算结果都属于s。
说明:
- *:通常指加法\((+或\oplus)\)和乘法\((\otimes或\times或\cdot)\)
- 结合律:\((a*b)*c=a*(b*c)\)
- 交换律:\(a*b=b*a\)
- 单位元\(e\):\(a*e=e*a=a\)(加法为0,乘法为1)
群
-
群的定义:设\(<G,*>\)是代数系统,*为G上的二元运算:
- 如果运算*是可结合的->\(<G,*>\)半群;
- 如果\(<G,*>\)为半群,且运算*存在单位元\(e \in G\)->\(<G,*>\)为幺半群;
- 如果\(<G,*>\)为幺半群,G中的任何元素元素x都有逆元\(x^{-1}\in G\)->\(<G,*>\)为群,简记为G
-
说明:
- 运算*为乘法(加法)时,G叫做乘(加)群;
- 群G中的元素个数叫做群G的阶,记为$ \left| G\right|$
- 如果群G中的运算*还满足交换律,那么G叫做一个交换群或者Abel(阿贝尔)群。
RSA
rsa密钥生成与正确性验证
rsa密钥生成
输出: $k_{pub}=(N,e) $ 和私钥:\(k_{pr}=(d)\)
- 选择两个大素数 \(p\) 和 \(q\)
- 计算 \(N=pq\)
- 计算 \(r=\Phi(n)=(p-1)(q-1)\)
- 选择满足以下条件的公开指数
- 计算满足一下条件的私钥 \(d\)
- 条件\(\gcd(e,\Phi(n))=1\)保证\(e\)的逆元存在模\(\Phi(n)\),因此私钥\(d\)始终存在
- 使用扩展欧几里得算法(EEA)(acm玩家:exgcd)立刻就可以计算出密钥\(d\)和\(e\)。
- 通常在\(0<e<\Phi(n)\)内选择一个公开参数,且\(e\)满足\(\gcd(\Phi(n),e)=1\)
- 将\(n\)和\(e\)用于EEA中即可得以下关系
如果\(\gcd(e,\Phi(n))=1\),则\(e\)是一个有效的公钥。此外从这里可以看出,使用扩展欧几里得算法得到的参数t即为e的逆元,因此有
如果\(e\)和\(\Phi(n)\)不是互素的,则课选择一个新的\(e\)值,并重复此过程。
- 注意,EEA的系数\(s\)对RSA而言不是必须的,因此也可以不计算
以上均参考《深入理解密码学》所写笔记
- 我发现ctf-wiki上的内容更适合我这样的萌新入门,所以参考暂时转为ctf-wiki的cry板块
- CTF-Wiki
RSA
基本原理
公钥与私钥的产生
1.随机选择两个不同大质数\(p\)和\(q\),计算\(N=p\times q\)
2.根据欧拉函数,求得\(r=\phi(N)=\phi(p)\phi(q)=(p-1)(q-1)\)
3.选择一个小于\(r\)的整数\(e\),使\(e\)和\(r\)互质。并求得\(e\)关于\(r\)的模反元素,命名为\(d\),有\(ed\equiv 1(\bmod r)\)
4.将\(p\)和\(q\)的记录销毁
此时,\((N,e)\)是公钥,\((N,d)\)是私钥。
消息加密
首先需要将消息\(m\)以一个双方约定好的格式转化为一个小于\(N\),且与\(N\)互质的整数\(n\)。如果消息太长,可以将消息分为几段,这也就是我们所说的块加密,后对于每一部分利用如下公式加密:
消息解密
利用密钥\(d\)进行解密。
正确性证明
略
Rsa e attack
小公钥指数攻击
\(e\)特别小,比如\(e\)为3
RSA衍生算法--Rabin算法
- \(e=2\)
Rsa d attack
Rsa module attack
共模攻击
攻击条件
当两个用户使用相同的模数\(N\)、不同的私钥时,加密同一明文消息时即存在共模攻击。
攻击原理
设两个用户的公钥分别为\(e_1\)和\(e_2\),且两者互质。明文消息为\(m\),密文分别为:
当攻击者截获\(c_1\)和\(c_2\)后,就可以恢复出明文。用扩展欧几里得算法求出\(re_1+se_2=1\bmod n\)的两个整数\(r\)和\(s\),由此可得
模不互素
找公因数