非对称加密原理和实现——RSA
Posted 一页破书
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了非对称加密原理和实现——RSA相关的知识,希望对你有一定的参考价值。
最近在做一个区块链相关的安全项目,之前掌握的密码学理论和编码经验很皮毛,跟不上项目要求,急需要补一下密码学。
(堡垒最容易从内部攻破,最近臭名昭著的长生生物兑水疫苗事件也是被内部员工曝光出来的——据说是加了几个月班,只给了两百多块钱的加班费;
此安全项目重点是防止内部操作人员、系统运维人员、系统开发&设计人员恶意侵入、仿冒、注入、后门等破坏攻击手段)
RSA基于大数质因式分解的,先看相关理论:
欧拉函数(符号Φ ):正整数N,1~N之间有多少个数与N互质?只看几种简单情况
N=1:Φ(1) =1
N是质数:Φ(N)=N-1
N是两个质数p、q乘积:Φ(N)= Φ(p) Φ(q)=(p-1)(q-1)
欧拉定理:
两个正整数a、n互质,a φ(n)-1是n的整数倍;
模反元素:
计算x使得a*x mod n=1,x就是a相对n的模反元素,记为:a-1 mod n
a和n互质的话,aφ(n)-1次方就是一个模反元素,
当然模反元素不唯一,aφ(n)-1+K*n都是a相对n的模反。
RSA过程:
选择两个很大的质数p、q
计算n=p*q
计算φ(n)=(p-1)(q-1)
选择一个与φ(n)互质并且小于φ(n)的数e
计算e对φ(n)的模反元素d,到此根据前面的欧拉函数、欧拉定理正向推导都很顺利
e*d-1=K*φ(n) =》 d=e(p-1)(q-1)-1 +K(p-1)(q-1)
当然秘钥生成过程不会直接计算e的(p-1)(q-1)指数,欧拉定理仅仅是证明了d的存在性,计算d可以用扩展欧几里得算法:
e*d≡ 1(mod φ(n)) 相当于求解模线性方程:e*d+φ(n) y =1 (e、d、φ(n)、y都是整数)
欧几里得扩展算法:对于两个正整数a、b,必定存在整数对x、y,使得ax+by=gcd(a,b);gcd ——最大公约数。递归计算过程如下:
欧几里得原理:gcd(a,b)=gcd(b,a mod b)
所以 :ax1+by1 = bx2+(a mod b) y2 = bx2 + (a-( a/b)b)y2=ay2+b(x2-(a/b)y2)
(此处a/b是整除,不带小数),由x2、y2可推出x1、y1:
x1=y2
y1= x2-(a/b)y2
ax1+by1 = bx2+(a mod b) y2 不断递归,b一定会变成0,递归结束。
因为e、φ(n) 互质,gcd(e,φ(n))=1,所以计算d可以套用扩展欧几里得算法:e*d+φ(n) y =1。
最后,n和e作为公钥公开发布;n和d作为私钥;
如果知道n和e,想推导出d,必须先把n分解为p、q;
公钥加密:m e mod n = c (m表示原文、c表示加密后的密文)
私钥解密:c d mod n = m,下面证明解密过程:
把c= m e - K*n代入解密方程:
m d*e mod n = m,只需要证明等式成立,继续代入d*e=K*φ(n)+1 ,
等式变为:m K*φ(n)+1 mod n = m
如果m和n互质,代入欧拉定理mφ(n)=1 + k*n,
m K*φ(n)+1 mod n = (1+k*n)k * m mod n = m,因为(1+k*n)k mod n = 1,证明等式成立。
如果m和n不互质,m是p或者q的倍数,证明过程稍微复杂一点。
私钥解密也不会直接计算cd,这个计算量更大,但是私钥持有者知道n、p、q,可以通过中国余数定理加速解密过程:
中国余数定理(孙子定理)针对一元线性同余方程组给出可解的判定条件和构造方式,一元同余方程组:
x≡a1 (mod m1)
x≡a2 (mod m2)
x≡an (mod mn)
定理给出:如果mi相互互质,对任意整数序列ai,方程组有解,构造方式:
1、构造M=m1*m2*m3*……*mn
2、构造Mi =M/mi
3、计算ti =Mi相对mi的模反
方程组的通用解:x= ∑aitiMi(i=1…n) + K*M
再套用到RSA私钥解密过程 cd mod n:
先定义 C1 = cd mod p、C2 = cd mod q
计算cd,找到不变量:
cd≡C1 (mod p)
cd≡C2 (mod q)
按中国余数定理计算:
M=pq=n
M1=M/p=q,M2=M/q=p
t1=q-1 mod p,t2=p-1 mod q
代入,计算出:
cd={ C1*(q-1 mod p)*q + C2*( p-1 mod q)*p } mod n
下面就是计算C1、C2:
cd mod p 根据费马小定理(欧拉定理的特例:ap-1≡1 (mod p) )可推倒:
d=K(p-1)+ [ d mod (p-1)]
cd mod p = c K(p-1)+ [ d mod (p-1)] mod p = c K(p-1) * c [ d mod (p-1)] mod p =
c [ d mod (p-1)] mod p
这样计算cd mod p 简化为 c [ d mod (p-1)] mod p。带入到cd=C1*(q-1 mod p)*q + C2*( p-1 mod q)*p,得到:
cd={ (c [ d mod (p-1)] mod p)*(q-1 mod p)*q +
(c [ d mod (q-1)] mod p)*( p-1 mod q)*p } mod n
理论之后,看代码实现(boundcycastle源码):
入口函数:
org.bouncycastle.crypto.generators.RSAKeyPairGenerator.generateKeyPair()
生成秘钥对的默认RSA参数:
finalstatic BigInteger defaultPublicExponent = BigInteger.valueOf(0x10001);
finalstaticintdefaultTests = 12;
param = newRSAKeyGenerationParameters(defaultPublicExponent,
new SecureRandom(),2048, defaultTests);
publicAsymmetricCipherKeyPair generateKeyPair()
{
BigInteger p, q, n, d, e, pSub1, qSub1, phi;
//
// p and qvalues should have a length of half the strength in bits
//
intstrength = param.getStrength();
intpbitlength = (strength + 1) / 2;
intqbitlength = strength - pbitlength;
intmindiffbits = strength / 3;
e = param.getPublicExponent();
// TODO Considergenerating safe primes for p, q (see DHParametersHelper.generateSafePrimes)
// (then p-1and q-1 will not consist of only small factors - see "Pollard'salgorithm")
//
// generate p,prime and (p-1) relatively prime to e
//
for (;;)
{这个for循环随机找到一个“可能的”素数,满足p-1与e互质
p = new BigInteger(pbitlength, 1, param.getRandom());
if (p.mod(e).equals(ONE))
{
continue;
}
p.isProbablePrime只保证p概率上是个素数,概率为1-1/(2*certainty) ,默认是23/24,如果不是素数会不会影响加解密呢?
if (!p.isProbablePrime(param.getCertainty()))
{
continue;
}
if (e.gcd(p.subtract(ONE)).equals(ONE))
{e和p-1互质
break;
}
}
//
// generate amodulus of the required length
//
for (;;)
{
// generate q,prime and (q-1) relatively prime to e,
// and notequal to p
//
for (;;) 生成q
{
q = new BigInteger(qbitlength, 1, param.getRandom());
if (q.subtract(p).abs().bitLength()< mindiffbits)
{
continue;
}
if (q.mod(e).equals(ONE))
{
continue;
}
if (!q.isProbablePrime(param.getCertainty()))
{
continue;
}
if (e.gcd(q.subtract(ONE)).equals(ONE))
{
break;
}
}
//
// calculatethe modulus
//
n = p.multiply(q);
if (n.bitLength() == param.getStrength())
{
break;
}
//
// if we gethere our primes aren't big enough, make the largest
// of the two pand try again
//
p = p.max(q);
}
if (p.compareTo(q) < 0)
{
phi = p;
p = q;
q = phi;
}
pSub1 = p.subtract(ONE);
qSub1 = q.subtract(ONE);
phi = pSub1.multiply(qSub1); phi=(p-1)*(q-1)
//
// calculatethe private exponent
//
d = e.modInverse(phi); d ——e相对(p-1)(q-1)模反
//
// calculatethe CRT factors
//
BigInteger dP, dQ, qInv;
dP = d.remainder(pSub1); dP——d mod (p-1)
dQ = d.remainder(qSub1); dQ —— d mod (q-1)
qInv = q.modInverse(p); qInv —— q相对p的模反
returnnewAsymmetricCipherKeyPair(
newRSAKeyParameters(false, n, e),
newRSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv)); 这几个值都是私钥的一部分
}
私钥加密过程:
org.bouncycastle.crypto.engines.RSACoreEngine.processBlock(BigInteger)
public BigIntegerprocessBlock(BigInteger var1) {
if (this.keyinstanceof RSAPrivateCrtKeyParameters){
RSAPrivateCrtKeyParameters var2 =(RSAPrivateCrtKeyParameters) this.key;
BigInteger var3 = var2.getP();
BigInteger var4 = var2.getQ();
BigInteger var5 = var2.getDP();
BigInteger var6 = var2.getDQ();
BigInteger var7 = var2.getQInv();
BigInteger var8 = var1.remainder(var3).modPow(var5, var3); (m mod p)d mod (p-1)mod p 即C1
BigInteger var9 = var1.remainder(var4).modPow(var6, var4); (m mod q)d mod (q-1)mod q即C2
BigInteger var10 = var8.subtract(var9); v
8-v9
var10 = var10.multiply(var7); (v8-v9)qInv
var10 = var10.mod(var3); (v8-v9)qInv mod p
BigInteger var11 = var10.multiply(var4); ((v8-v9)qInv mod p)q
var11 = var11.add(var9);
returnvar11;
} else {
returnvar1.modPow(this.key.getExponent(), this.key.getModulus());
}
}
{ [(m mod p)d mod (p-1)mod p - (m mod q)d mod (q-1)mod q ]*(qInv) mod p } q +
(m mod q)d mod (q-1)mod q
=
[(m mod p)d mod (p-1)mod p ]*qInv*q +
[(m mod q)d mod (q-1)mod q] * (1-qInv*q) mod q
1-qInv*q 泛化为 1+kq= p-1 mod q)*p,这样就和上面中国余数定理简化的公式一致。
RSAPrivateCrtKeyParameters里面的Crt就是中国余数定理 Chinese Remainder Theorem的首字母缩写。
最后,知道RSA的私钥能否推导出公钥?
1、假设私钥是CRT格式,私钥本身包含了n,e,d,p,q等元素,n和e就是公钥;
2、非CRT格式的私钥只包括n、d,多数情况下生成RSA公私钥对e都是固定选择65537,其他情况为了公钥加密解密耗时短,选择e也不会太多,所以知道n、d 可以在log(N)线性时间内推导出e。
以上是关于非对称加密原理和实现——RSA的主要内容,如果未能解决你的问题,请参考以下文章