文章目录
RSA是一种公钥密码算法,它的名字是由它的三位开发者,即Ron Rivest、Adi Shamir 和 Leonard Adleman 的姓氏的首字母组成的。RSA可以被用于公钥密码和数字签名。RSA是被研究得最广泛的公钥算法,从提出到现在已近三十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。1983年麻省理工学院在美国为RSA算法申请了专利。
RSA的安全性依赖于大数分解。换句话说,RSA的难度与大数分解难度等价,一旦发现了对大整数进行质因数分解的高效算法,RSA就能够被破译。这点将在下述对 N 的讨论着重体现。
| 参数 | 解释 | 公式 | 描述 |
|---|---|---|---|
| P、Q | 质数 | P*Q=N | 分解模数N后得到的值 |
| N | 公共模数 | N=P*Q | 在RAS中进行模运算 |
| E | 公钥指数 | gcd(φ,e)=1 | 1<e<φ |
| D | 私钥指数 | gcd(φ,d)=1 | 1<d<φ |
| φ | 欧拉公式 | φ=(P-1)*(Q-1) | / |
| c | 密文 | c=me mod N | / |
| d | 明文 | m=cd mod N | / |
由上面的参数表可知,RSA加密过程可以用下面这个公式表示
c ≡ m e mod N
也就是说,RSA的密文是对代表明文的数字 m 的 e 次方对 N 求余的结果
公钥
上述加密算法中出现的两个数—— E 和 N ,到底是什么数呢?由上面的加密算法可知,在已知明文的情况下,只要只要 E 和 N 这两个数,任何人都可以完成对加密的运算。所以说, E 和 N 是RSA加密的密钥,换句话说,E 和 N 的组合就是公钥,表示为公钥是(E,N)
公钥是可以任意公开的
同样由上面的参数表可知,RSA解密过程可以用下面这个公式表示
m≡cd mod N
也就是说,RSA的明文是对代表密文的数字 c 的 d 次方对 N 求余的结果
可以发现形式上跟加密算法高度对称
私钥
参考公钥的解释,私钥也就明了了。在已知密文的情况下,只要只要 D 和 N 这两个数,任何人都可以完成对解密的运算。所以说, D 和 N 是RSA解密的密钥,换句话说,D 和 N 的组合就是私钥,表示为私钥是(D,N)
私钥必须妥善保管,不能告诉任何人

由上述分析可知,加解密的过程需要三个参数 E、D、N,那么这三个参数该怎么生成呢?由于 E 和 N 是公钥,D 和 N 是私钥,求这三个数的过程就是生成密钥对。生成步骤如下:
1、求N
2、求φ
3、求E
4、求D
求N
首先准备两个很大的质数 P、Q。上述所说的算法安全性与大数分解有关,就体现在这了,我们反过来想,如果 p 和 q 选的很小,那对于 N 的求解将会变得非常简单,密码就容易被破译;但是物极必反,也不能选的太大,太大会使得计算时间大大延长。
准备好之后,N 由以下公式求得
P*Q=N
求φ
φ这个数在加密解密的过程中都不曾出现,它只出现在生成密钥对的过程中。由下列公式求得
φ=(P-1)*(Q-1)
求E
e 的求取基于上述的 φ 值。首先明确 e 的取值范围 1<e<φ,并且 gcd(φ,e)=1(φ 与 e 的最大公约数为1,即两者互质)。之所以要加上1这个条件,是为了保证一定存在解密时需要使用的参数 D
至此,我们生成了密钥对中的公钥
求D
d 的求取基于上述的 e 值和 φ 值。首先明确 d 的取值范围 1<d<φ,并且 gcd(φ,d)=1。d 的求解方式如下
e*d mod φ=1
至此,我们生成了密钥对中的私钥

密钥对生成
① 求N
首先随便找两个素数,比如3、11(这边自己实验就取小数展示)
p = 3
q = 11
得到 N
N = 3*11 = 33
② 求φ
φ = 2*10= 20
③ 求e
gcd(φ,e)=1
满足条件的有很多,3,7,11,13,17,19… 这边我们选择3来作为 e。
至此,e = 3 ,N = 33,这就是公钥
④ 求d
e*d mod φ=1
容易得 d = 7
至此,d = 7 ,N = 33,这就是私钥
加密
要加密的明文必须是小于 N 的数,也就是小于33的数,这边就随便取一个5吧
c=me mod N = 53 mod 33 = 26
解密
m=cd mod N = 267 mod 33 = 5
对于常规得CTF题来说,通常会给大家公钥指数 E 和公共模数 N,而这个模数 N 是非常大得数字。我们要做的是将它分解成两个指数 p,q,进而求得 φ,再根据公式求得私钥指数,最后将密文转换成明文。
如何将大整数 N 分解呢?
1、当 N 的长度较小时,采用爆破
2、当 N 满足因数p、q相差较小或相差很大时,可以采用离线工具yafu来分解
3、当 N 的位数过大时,且不满足上述条件,可以用在线网站 factordb。该网站类似于彩虹表,将已被分解的大数结果存储起来,只需要输入查询即可。
逆元是什么?为什么突然讨论逆元?
还记得上面求解私钥指数d的公式吗?
e*d mod φ=1
这个公式也可以写成
e*d ≡ 1(mod φ)
如果一个线性同余方程 ax ≡ 1(mod b),则 x 称为 a mod b 的逆元,记作a-1 。一个数有逆元的充分必要条件是gcd(a,b)=1,此时逆元唯一存在 。
此处为什么讨论逆元呢?其一,RSA中有逆元的概念;其二,中国剩余定理(CRT)可与 RSA 算法结合来进行加解密,CRT又逃不开逆元的概念,所以就说了。逆元也是数论中一个十分重要的概念,当我们要求 (a / b) mod p的值,且a很大,大到会溢出;或者说b很大,达到会爆精度。无法直接求得a/b的值时,我们就要用到乘法逆元。
所以上述求解私钥指数d,可以说 e 的逆元是 d mod φ
如果 p 是一个质数,而整数 a 不是 p 的倍数,则
a p−1 ≡ 1 (mod p)
可得
a * a p−2 ≡ 1 (mod p)
所以 a 的逆元即为 a p-2 (mod p)
之后利用快速幂求解
typedef long long ll;
ll mod = 1e9 + 7;
ll quick_pow(ll base,ll idx){
ll ans = 1;
while(idx){
if(idx & 1){
ans *= base;
ans %= mod;
}
base *= base;
base %= mod;
idx >>= 1;
}
return ans;
}
ll inv(ll a){
return quick_pow(a,mod-2);
}
逆元的含义决定了ax ≡ 1(mod b)等价于ax = kb+1
void exgcd(int a, int b, int& x, int& y) {
if (b == 0) {
x = 1, y = 0;
return;
}
exgcd(b, a % b, y, x);
y -= a / b * x;
}
网上介绍很多,具体可以参考中国剩余定理(孙子定理)
前面多次讨论过了,RSA的难点就在于对于大整数 N 的分解。有没有啥方法能简化这个过程呢?
有,就是上述的中国剩余定理。由中国剩余定理可知,设 p 和 q 是互相独立的大素数,n 为 p*q,对于任意 (m1, m2),且 0<=m1< p,0<=m2< q
必然存在一个唯一的m ,0<=m< n,使得
m1 = m mod p
m2 = m mod q
换句话说,给定一个(m1,m2),其满足上述等式的m必定唯一存在。所以解密RSA 的流程 m = c d mod n,可以分解为
m1 = c d mod p
m2 = c d mod q
然后再计算m
但是等式 c d mod p 或者 c d mod q ,模数虽然从n降为p或q了,但是私钥指数指数d还是较大,运算还是比较消耗性能。所以我们还需要降低指数。
仔细看等式 c d mod p
令d = k(p-1) + r 则 c d mod p
= c k(p-1)+r mod p
= c r * c k(p-1) mod p
因为 c (p-1) mod p = 1 (欧拉定理)
= c r mod p
r 是 d 除 p-1 的余数,即 r = d mod (p-1) 所以 c d mod p 可以降阶为 c d mod p-1 mod p,同理,c d mod q可以降阶为 c d mod q-1 mod q。
可令
dp = d mod p-1
dq = d mod q-1
这样 m1 和 m2 就降为
m1 = c dp mod p
m2 = c dq mod q
模数都降的差不多了。想要求解明文,除了上述的 p、q、d、dp、dq,我们还需要 q 对 p 的逆元
qinv = q -1 mod p
结合上述的公式,我们得到最终的明文公式
h = qinv(m1−m2) mod p
m = m2+hq mod p∗q
目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非
我有一个.pfx格式的证书,我需要使用ruby提取公共(public)、私有(private)和CA证书。使用shell我可以这样做:#ExtractPublicKey(askforpassword)opensslpkcs12-infile.pfx-outfile_public.pem-clcerts-nokeys#ExtractCertificateAuthorityKey(askforpassword)opensslpkcs12-infile.pfx-outfile_ca.pem-cacerts-nokeys#ExtractPrivateKey(askforpassword)o
我在加密来self正在使用的第三方供应商的值时遇到问题。他们的指令如下:1)Converttheencryptionpasswordtoabytearray.2)Convertthevaluetobeencryptedtoabytearray.3)Theentirelengthofthearrayisinsertedasthefirstfourbytesontothefrontofthefirstblockoftheresultantbytearraybeforeencryption.4)EncryptthevalueusingAESwith:1.256-bitkeysize,2.25
首先,关于我们系统的一些信息,它基本上是建筑行业的电子招标解决方案。所以:列表项我们的系统有多家公司每个公司都有多个用户每家公司可以创建多个拍卖然后其他公司可以为可用的拍卖提交他们的出价。一个出价包含数百或数千个单独的项目,我们只需要加密这些记录的“价格”部分。我们面临的问题是,我们的大客户不希望我们知道投标价格,至少在投标过程中是这样,这是完全可以理解的。现在,我们只是通过对称加密对价格进行加密,因此即使价格在数据库中有效加密,他们担心的是我们拥有解密价格的key。因此,我们正在研究某种形式的公钥加密系统。以下是我们对解决方案的初步想法:当一家公司注册时,我们会使用OpenSSL为其
我正在尝试对某些帖子的评论使用简单的身份验证。用户使用即时ID和密码输入评论我使用“bcrypt”gem将密码存储在数据库中。在comments_controller.rb中像这样@comment=Comment.new(comment_params)bcrypted_pwd=BCrypt::Password.create(@comment.user_pwd)@comment.user_pwd=bcrypted_pwd当用户想要删除他们的评论时,我使用data-confirm-modalgem来确认数据在这部分,我必须解密用户输入的密码以与数据库中的加密密码进行比较我怎样才能解密密码,
1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva
我在Rails中有一个具有以下方法的应用程序,该方法可以加密和解密文本并与Java客户端通信。defencrypt(string,key)cipher=OpenSSL::Cipher::AES.new(128,:CBC)cipher.encryptcipher.padding=1cipher.key=hex_to_bin(Digest::SHA1.hexdigest(key)[0..32])cipher_text=cipher.update(string)cipher_textexcenddefhex_to_bin(str)[str].pack"H*"enddefbin_to_hex(
我一直在尝试用Ruby实现Luhn算法。我一直在执行以下步骤:该公式根据其包含的校验位验证数字,该校验位通常附加到部分帐号以生成完整帐号。此帐号必须通过以下测试:从最右边的校验位开始向左移动,每第二个数字的值加倍。将乘积的数字(例如,10=1+0=1、14=1+4=5)与原始数字的未加倍数字相加。如果总模10等于0(如果总和以零结尾),则根据Luhn公式该数字有效;否则无效。http://en.wikipedia.org/wiki/Luhn_algorithm这是我想出的:defvalidCreditCard(cardNumber)sum=0nums=cardNumber.to_s.s
下面是我写的一个计算斐波那契数列中的值的方法:deffib(n)ifn==0return0endifn==1return1endifn>=2returnfib(n-1)+(fib(n-2))endend它工作到n=14,但在那之后我收到一条消息说程序响应时间太长(我正在使用repl.it)。有人知道为什么会这样吗? 最佳答案 Naivefibonacci进行了大量的重复计算-在fib(14)fib(4)中计算了很多次。您可以将内存添加到您的算法中以使其更快:deffib(n,memo={})ifn==0||n==1returnnen
为了防止在迁移到生产站点期间出现数据库事务错误,我们遵循了https://github.com/LendingHome/zero_downtime_migrations中列出的建议。(具体由https://robots.thoughtbot.com/how-to-create-postgres-indexes-concurrently-in概述),但在特别大的表上创建索引期间,即使是索引创建的“并发”方法也会锁定表并导致该表上的任何ActiveRecord创建或更新导致各自的事务失败有PG::InFailedSqlTransaction异常。下面是我们运行Rails4.2(使用Acti