理解RSA算法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解RSA算法相关的知识,希望对你有一定的参考价值。
参考技术A如果公钥加密的信息只有私钥解得开,只要私钥不泄露,通信就是安全的.
欧拉函数 ,在数论中,对正整数n,欧拉函数φ(n)是小于或等于n的正整数中与n互质的数的数目.例如:φ(8) = 4,因为1,3,5,7均与8互质.
通式:
如果n=1,则 φ(1) = 1 。因为1与任何数(包括自身)都构成互质关系。
如果n是质数,则 φ(n)=n-1 。因为质数与小于它的每一个数,都构成互质关系。比如5与1、2、3、4都构成互质关系。
如果n是质数的某一个次方,即 n = p^k (p为质数,k为大于等于1的整数),则
如果n可以分解成两个互质的整数之积
n = p1 × p2 则 φ(n) = φ(p1p2) = φ(p1)φ(p2)
如果两个正整数a和n互质,则n的欧拉函数 φ(n) 可以让下面的等式成立:
如果两个正整数a和n互质,那么一定可以找到整数b,使得 ab-1 被n整除,或者说ab被n除的余数是1。
这时,b就叫做a的"模反元素"。
比如,3和11互质,那么3的模反元素就是4,因为 (3 × 4)-1 可以被11整除。显然,模反元素不止一个, 4加减11的整数倍都是3的模反元素 ...,-18,-7,4,15,26,...,即如果b是a的模反元素,则 b+kn 都是a的模反元素。
比如,老张和老王是两名地下工作者,老张要向老王传达一个机密的文件.这时老张想到了RSA算法.
(1) 随机选择两个不相等的质数p,q.
这时,老张选择了61和53.
(2) 计算p和q的乘积n.
n的长度就是密钥长度。3233写成二进制是110010100001,一共有12位,所以这个密钥就是12位。实际应用中,RSA密钥一般是1024位,重要场合则为2048位。
(3) 计算n的欧拉函数φ(n).
根据上面所介绍的欧拉定理第四种情况:
(4) 随机选择一个整数e,条件是1< e < φ(n),且e与φ(n) 互质.
这时,老张从1-3120之间,随机选择了17.(实际应用中,常常选择65537).
(5) 计算e对于φ(n)的模反元素d
所谓"模反元素"就是指有一个整数d,可以使得ed被φ(n)除的余数为1。
这个公式等价于
于是,找到模反元素d,实质上就是对下面这个二元一次方程求解。
那么,已知e = 17,φ(n) = 3120 ,求x的值
这个方程可以用"扩展欧几里得算法"求解,此处省略具体过程。总之,老张算出一组整数解为 (x,y)=(2753,15),即 d=2753。
(6) 将n和e封装成公钥,n和d封装成私钥
n=3233,e=17,d=2753,所以公钥就是 (3233,17),私钥就是(3233, 2753),即公钥为( n,e ),私钥为( n,d )。
实际应用中,公钥和私钥的数据都采用 ASN.1 格式表达。
老张进行了这些计算后,整理了下上面所提到的数字:
这六个数字之中,公钥用到了两个(n和e),其余四个数字都是不公开的。其中最关键的是d,因为n和d组成了私钥,一旦d泄漏,就等于私钥泄漏。
老张想,有没有可能在已知n和e的情况下,也就是知道公钥的情况下,推导出d?
结论:如果n可以被因数分解,d就可以算出,也就意味着私钥被破解。可是,大整数的因数分解,是一件非常困难的事情.
有了公钥和密钥,就能进行加密和解密了。
1.加密要用公钥 (n,e)
假设老张要向老王发送加密信息m,他就要用老王的公钥 (n,e) 对m进行加密。这里需要注意,m必须是整数(字符串可以取ascii值或unicode值),且m必须小于n。
所谓"加密",就是算出下式的c:
老王的公钥是 (3233, 17),老张的m假设是65,那么可以算出下面的等式:
于是,c等于2790,老张就把2790发给了老王。
2.解密要用私钥(n,d)
老王拿到老张发来的2790以后,就用自己的私钥(3233, 2753) 进行解密。可以证明,下面的等式一定成立:(证明过程略,有兴趣可以看阮一峰的博客)
也就是说,c的d次方除以n的余数为m。现在,c等于2790,私钥是(3233, 2753),那么,老王算出
因此,老王知道了老张加密前的原文就是65。
我们可以看到,如果不知道d,就没有办法从c求出m。而前面已经说过,要知道d就必须分解n,这是极难做到的,所以RSA算法保证了通信安全。
你可能会问,公钥(n,e) 只能加密小于n的整数m,那么如果要加密大于n的整数,该怎么办?有两种解决方法:一种是把长信息分割成若干段短消息,每段分别加密;另一种是先选择一种"对称性加密算法"(比如DES),用这种算法的密钥加密信息,再用RSA公钥加密DES密钥。
再谈加密-RSA非对称加密的理解和使用
前言
随着互联网越来越渗透入我们生活的方方面面,各种私密信息在网络中传播,为了保证信息的真实可靠,在我们对其安全性的要求也越来越高,对此,加密是一个永远不过时的话题。非对称加密,全站HTTPS等,深入了解,总会遇到RSA加密算法。在一些特殊行业,如博主工作的互联网金融,RSA加密算法的重要性更是非同一般。
可能由于密码学的枯燥,还有加密各种标准的混杂,加密与解密难以测试与验证,再加上大公司有大牛写框架,小公司多用demo,网上有关加密的知识不是很多,一开始尝试了解比较困难,所以我总结一下最近学习的一些知识,希望能帮到需要的人。
由于RSA算法原理牵涉到的都是些数学知识,作为一个数学渣,不拿出来误导别人了。有感兴趣的,可以看一下阮一峰大神的博客:
以前写过一篇PHP使用openssl扩展的博客:,讲了一些加密基础和PHP中如何进行加密。本文主要聊一聊非对称加密的相关知识、RSA加密算法的数字证书操作,也会附带一些其他相关知识和使用心得。如文章有错漏之处,烦请指出,谢谢。
数字证书
公钥传输问题
在密文传输过程中,客户端(Client C)向服务器(Server S)发送数据,C使用S的公钥加密,这样只有S使用自己的私钥解密才能拿到信息,其他人即使得到了数据,没有S的私钥也没用。
但是如果有一个黑客H告诉C自己是S,并将自己的假公钥发送给C,那么C用假公钥加密数据并将数据发送给了H,那么H就顺利得到了信息,无法起到数据加密的作用。
这就需要一个中间人来颁发一个身份证明来证明S是真的S。
数字证书认证中心
这个中间人就是数字证书认证机构。
数字证书认证中心(Certificate Authority)(也被称为证书认证机构或CA)是指颁发证书、废除证书、更新证书、验证证书、管理密钥的机构。它能在认证某组织或个人后分发证书的机构,它验证的信息包括已签约的证书,当然它也负责吊销有危害的证书。
数字证书
中间人颁发的身份证明就是数字证书。
数字证书是一个包含 证书拥有者公钥、证书拥有者信息、证书认证中心数字签名的文件。 拿到数字证书后,我们解析证书的证书认证机构数字签名确保证书是真的,且没有被篡改过后,取得其中的公钥,然后就可以使用此公钥与浏览器进行交互了。
根证书
CA 这么重要,可是怎么能证明 CA 是真的呢?这个不用担心,许多 CA 都有嵌入在浏览器中的根证书,所以浏览器能自动识别它们。在一些API交互中,如请求支付宝的接口时,我们已经在本地存储了支付宝的证书了。
不用担心本地的根证书安全问题,如果本地存储的根证书都被修改了,那么加解密也就没有什么意义了。
证书链
由于世界上需要证书的组织众多,任何一家 CA 也不能处理全部的认证请求。于是大大小小的 CA 出现了,可是每个客户端不可能把他们的证书作为根证书全存储起来。
于是CA建立自上而下的信任链,下级 CA 信任上级 CA,下级 CA 由上级 CA 颁发证书并认证。因为下级 CA 的证书是用上级 CA 的密钥加密的,而上级 CA 的密钥只有自己知道,因此别人无法冒充上级 CA 给别人发证书。
在进行证书认证时,服务器会发给客户端一个包含着“证书机构证书”的证书,会层层链接到最上层的 CA,我们本地拥有最上级的 CA 的证书,如果能证明此 CA 的真实性,那么也便能证明服务器证书的可靠。
证书标准
X.509是目前最能用的证书标准, 证书由用户公共密钥和用户标识符组成。此外还包括版本号、证书序列号、CA标识符、签名算法标识、签发者名称、证书有效期等信息。这一标准的最新版本是X.509 v3,它定义了包含扩展信息的数字证书。该版数字证书提供了一个扩展信息字段,用来提供更多的灵活性及特殊应用环境下所需的信息传送。
RSA加密标准
公钥加密标准
公钥加密标准(Public Key Cryptography Standards, PKCS),此系列标准的设计与发布皆由RSA信息安全公司所制定。包括证书申请、证书更新、证书作废表发布、扩展证书内容以及数字签名、数字信封的格式等方面的一系列相关协议。
目前在使用的最高版本为 PKCS#12,这版本也是我工作中使用最多的版本,此外我还接触过 PKCS#7 版本,java多用 PKCS#8 版本,下面分别说一下。
PKCS#7:
定义一种通用的消息语法,包括数字签名和加密等用于增强的加密机制,PKCS#7与PEM兼容,所以不需其他密码操作,就可以将加密的消息转换成PEM消息。规范了以公开密钥基础设施(PKI)所产生之签名/密文之格式。其拓展数字证书在 S/MIME与CMS 的应用,PKCS#7一般主要用来做数字信封。
PKCS#8
描述私有密钥信息格式,该信息包括公开密钥算法的私有密钥以及可选的属性集等,Apache读取证书私钥的标准,在JAVA平台中使用。(接入一些支付公司中经常会提供此格式的密钥,有些印象)
PKCS#12:
描述个人信息交换语法标准。描述了将用户公钥、私钥、证书和其他相关信息打包的语法。 含有私钥,同时可以有公钥,有口令保护 格式一般为 .pfx
。 由于它可以加密码保护,打开时需要一串特殊密码,所以相对安全些。
证书和密钥文件格式
需要注意:证书文件格式与加密标准并没有严格的对应关系,证书文件格式是存储证书的方式不同,可能存储的内容也略有不同。而加密标准是使用证书文件进行加解密的方式不同。
pem格式
最普通的证书格式,以-----BEGIN CERTIFICATE-----
开头,以-----END CERTIFICATE-----
结尾;有些pem证书把私钥也放在了一个文件中,但是很多平台还是需求证书和私钥分开放在不同的文件中。 pem证书有以下特点:
base64编码;
有.pem, .crt, .cer, .key文件后缀;
Apache等类似服务器使用pem格式证书;
der格式
der格式是pem格式证书的二进制格式,证书和私钥都可以以der格式存储。 其特点为:
二进制格式;
以.cer或.der格式为后缀;
常被用于java平台;
PKCS#7格式
它是一种PKCS#7格式以-----BEGIN PKCS-----
开头,以-----END PKCS7-----
结尾,它只能保存证书或证书链,不能保存私钥。 其特点为:
base64编码;
文件后缀为 .p7p, .p7c;
window或java tomcat等平台支持此类型;
PKCS#12(pfx)格式
它能把服务器证书(包括公钥),中间证书和私钥存储在一起。特点为:
二进制文档;
以 .pfx 或.p12为后缀;
经常在windows系统内被用于导入导出证书和私钥;
打开可能需要额外密码;
密钥的保存
对于密钥(单指公私钥)的保存,并不需要特殊的格式,直接将base64编码后的密钥作为字符串存入文档即可。
RSA加密操作
密钥生成和使用
openssl genrsa -out rsa_private_key.pem 1024 // 生产一个1024位的私钥, 保存在 rsa_private_key.pem 文件里
openssl rsa -in rsa_private_key.pem -pubout -out pub.pem // 通过私钥生产公钥
此外,介绍一下openssl提供的一个测试加密速度的小工具,可以查看一定时间内某算法计算的次数,让我们对各种加密算法的速度有一个大概的认识。
openssl speed algciper
eg: openssl speed rsa1024
openssl speed des-ede3
格式转换
从pfx文件中提取公私钥
openssl pkcs12 -in source.pfx -nocerts -nodes -out key.key // 从pfx文件中获取到密匙对文件,有时会需要密码
opensll rsa -in key.key -out pri.key // 从密匙对文件中获取到私匙。
opensll rsa -in key.key -pubout -out pub.key // 从密匙对文件中获取到公匙;
openssl pkcs8 -in pri.key -out repri.key -outform der -nocrypt -topk8 //java语言用
各种证书之间的互相转换
PEM to DER
openssl x509 -outform der -in certificate.pem -out certificate.der
—————————————————————————————————–
PEM to P7B
openssl crl2pkcs7 -nocrl -certfile certificate.cer -out certificate.p7b -certfile CAcert.cer
———————————————————————————————————————————-
PEM to PFX
openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CAcert.crt
——————————————————————————————————————————————————
DER to PEM
openssl x509 -inform der -in certificate.cer -out certificate.pem
————————————————————————————————
P7B to PEM
openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
————————————————————————————————-
P7B to PFX
openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
openssl pkcs12 -export -in certificate.cer -inkey privateKey.key -out certificate.pfx -certfile CAcert.cer
——————————————————————————————————————————————————-
PFX to PEM
openssl pkcs12 -in certificate.pfx -out certificate.cer -nodes
PHP中使用RSA
作为一个PHPer,当然还要提一下在 PHP 中如何使用 RSA 加密,所用工具依然是强大的openssl扩展:
# 从pfx文件中提取私钥和证书(需要传入密码 $password):
openssl_pkcs12_read($file_content, $key, $password);
$key['pkey'] => 私钥
$key['cert'] => 证书
# 解析x.509证书
openssl_x509_read($cert);
# 以pkcs7加密标准加解密/签名验签数据:需要注意pkcs7操作都需要使用一个临时文件,多进程时要考虑一下文件冲突问题,还有别忘了最后释放临时文件。
openssl_pkcs7_encrypt()/openssl_pkcs7_decrypt()
openssl_pkcs7_sign()/openssl_pkcs7_verify()
# 从字符串中获取公私钥:
openssl_pkey_get_private()/openssl_pkey_get_public()
# RSA以pkcs#12标准加解密/签名验签数据:
openssl_private(public)_encrypt()/openssl_private(public)_decrypt()
小结
最后不得不吐槽一下各种不统一标准的支付公司,可能由于系统老,有各种各样的奇葩的加解密要求。。。 不像支付宝和微信这种大平台,纯纯的 RSA 操作,使用起来非常方便。希望跟我以前一样饱受加解密折磨,最后还一头雾水的看官能通过此文有所收获。
随着硬件的快速发展,加解密带来的资源消耗已经越来越微不足道了,我相信不仅是金融等行业,对其他IT行业来说,加解密特别是非对称加密也一定会越来越重要,有备无患嘛。
最后,如果您觉得此文对您稍有帮助,可以点击下方推荐。持续更新,欢迎关注。
参考:
本文转载自:http://www.cnblogs.com/zhenbianshu/p/6285437.html
PHPer升级为大神并不难!
以上是关于理解RSA算法的主要内容,如果未能解决你的问题,请参考以下文章