RSA算法及数学原理

一、RSA算法

1.引入:

RSA加密算法是一种非对称加密算法。在公钥加密标准电子商业中RSA被广泛使用。RSA是1977年罗纳德·李维斯特(Ron Rivest)、阿迪萨默尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

1973年,在英国政府通讯总部工作的数学家克利福德·柯克斯(Clifford Cocks)在一个内部文件中提出了一个相应的算法,但他的发现被列入机密,一直到1997年才被发表。

对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。假如有人找到一种快速因数分解的算法的话,那么用RSA加密的信息的可靠性就肯定会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。但在分布式计算技术量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战。

2.操作:

公钥和私钥的产生

假设Alice想要通过一个不可靠的媒体接收Bob的一条私人讯息。她可以用以下的方式来产生一个公钥和一个私钥

  1. 随意选择两个大的质数pqp不等于q,计算N=pq
  2. 根据欧拉函数,不大于N且与N互质的整数个数为(p-1)(q-1)
  3. 选择一个整数e与(p-1)(q-1)互质,并且e小于(p-1)(q-1)
  4. 用以下这个公式计算dd× e ≡ 1 (mod (p-1)(q-1))
  5. pq的记录销毁。

(N,e)是公钥,(N,d)是私钥。(N,d)是秘密的。Alice将她的公钥(N,e)传给Bob,而将她的私钥(N,d)藏起来。

[编辑]加密消息

假设Bob想给Alice送一个消息m,他知道Alice产生的Ne。他使用起先与Alice约好的格式将m转换为一个小于N的整数n,比如他可以将每一个字转换为这个字的Unicode码,然后将这些数字连在一起组成一个数字。假如他的信息非常长的话,他可以将这个信息分为几段,然后将每一段转换为n。用下面这个公式他可以将n加密为c

 n^e \equiv c\ (\mathrm{mod}\ N)

计算c并不复杂。Bob算出c后就可以将它传递给Alice。

[编辑]解密消息

Alice得到Bob的消息c后就可以利用她的密钥d来解码。她可以用以下这个公式来将c转换为n

 c^d \equiv n\ (\mathrm{mod}\ N)

得到n后,她可以将原来的信息m重新复原。

解码的原理是

 c^d \equiv n^{e \cdot d}\ (\mathrm{mod}\ N)

以及ed ≡ 1 (mod p-1)和ed ≡ 1 (mod q-1)。由费马小定理可证明(因为pq是质数)

 n^{e \cdot d} \equiv n\ (\mathrm{mod}\ p)      和       n^{e \cdot d} \equiv n\ (\mathrm{mod}\ q)

这说明(因为pq不同的质数,所以pq互质)

 n^{e \cdot d} \equiv n\ (\mathrm{mod}\ pq)

[编辑]签名消息

RSA也可以用来为一个消息署名。假如甲想给乙传递一个署名的消息的话,那么她可以为她的消息计算一个散列值(Message digest),然后用她的密钥(private key)加密这个散列值并将这个“署名”加在消息的后面。这个消息只有用她的公钥才能被解密。乙获得这个消息后可以用甲的公钥解密这个散列值,然后将这个数据与他自己为这个消息计算的散列值相比较。假如两者相符的话,那么他就可以知道发信人持有甲的密钥,以及这个消息在传播路径上没有被篡改过。

3.速度与安全性:

由于进行的都是大数计算,使得RSA最快的情况也比DES慢上好几倍,无论是软件还是硬件实现。速度一直是RSA的缺陷。一般来说只用于少量数据加密。RSA的速度比对应同样安全级别的对称密码算法要慢1000倍左右。

假设偷听者乙获得了甲的公钥Ne以及丙的加密消息c,但她无法直接获得甲的密钥d。要获得d,最简单的方法是将N分解为pq,这样她可以得到同余方程d× e ≡ 1 (mod (p-1)(q-1))并解出d,然后代入解密公式

 c^d \equiv n\ (\mathrm{mod}\ N)

导出n(破密)。但至今为止还没有人找到一个多项式时间的算法来分解一个大的整数的因子,同时也还没有人能够证明这种算法不存在(见因数分解)。

至今为止也没有人能够证明对N进行因数分解是唯一的从c导出n的方法,但今天还没有找到比它更简单的方法。(至少没有公开的方法。)

因此今天一般认为只要N足够大,那么黑客就没有办法了。

假如N的长度小于或等于256,那么用一台个人电脑在几个小时内就可以分解它的因子了。1999年,数百台电脑合作分解了一个512位长的N。今天对N的要求是它至少要1024位长。

1994年彼得·秀尔(Peter Shor)证明一台量子计算机可以在多项式时间内进行因数分解。假如量子计算机有朝一日可以成为一种可行的技术的话,那么秀尔的算法可以淘汰RSA和相关的衍生算法。(即依赖于分解大整数困难性的加密算法)

假如有人能够找到一种有效的分解大整数的算法的话,或者假如量子计算机可行的话,那么在解密和制造更长的钥匙之间就会展开一场竞争。但从原理上来说RSA在这种情况下是不可靠的。

4.举例:

找两个素数:
p=47
q=59
这样
n=p*q=2773
t=(p-1)*(q-1)=2668
取e=63,满足e<t并且e和t互素
用perl简单穷举可以获得满主 e*d%t ==1的数d:
C:\Temp>perl -e "foreach $i (1..9999){ print($i),last if $i*63%2668==1 }"
847
即d=847

最终我们获得关键的
n=2773
d=847
e=63

取消息M=244我们看看

加密:

c=M**d%n = 244**847%2773
用perl的大数计算来算一下:
C:\Temp>perl -Mbigint -e "print 244**847%2773"
465
即用d对M加密后获得加密信息c=465

解密:

我们可以用e来对加密后的c进行解密,还原M:
m=c**e%n=465**63%2773 :
C:\Temp>perl -Mbigint -e "print 465**63%2773"
244
即用e对c解密后获得m=244 , 该值和原始信息M相等。

5.应用:

1982年,Rivest、Shamir和Adleman三个创始人正式建立了RSA Security。2006年,RSA Security被EMC公司收购,成为RSA,EMC安全事业部。收购RSA的同时,EMC还收购了NetworkIntelligence,为RS带来了行业领先的信息安全和事件管理(SIEM)解决方案,并将其整合到RSA事业部。

RSA的业务有四块:

一是身份认证,RSA的双因认证技术,是全球最安全的身份认证技术。所谓双因素认证,是除了传统的静态密码保护,再加一个动态密码。动态密码由专门的硬件令牌生成,每分钟改变一次;认证服务器上基于同样的密码算法,每分钟生成一次密码。用户手里有硬件令牌,才能提供正确的密码,从而提高了安全性。

二是反网络欺诈,RSA身份保护和验证套件提供了一个最完整、最创新的强认证和防欺诈技术组合,设计用于保护机构及其在线用户对付最新的外部威胁。它是一个完整的软件即服务(SaaS)的组合,用于增加在线和远程交易,激发网络用户信心,帮助企业减少网络欺诈损失及相关防治成本。

三是信息安全与事件管理。当前,主要客户是上市公司。用专门的设备搜集整个IT系统的设备日志,包括网络、服务器、存储多个方面,并对这些日志进行自动分析,发现安全漏洞。

四是防数据丢失。可以发现、监测和保护企业的敏感数据,无论在数据中心、网络还是终端上都不被丢失、泄漏或滥用。


二、RSA用到的数学原理

(未完待续)


三、程序实现

前期准备:下载Crypt库

源代码

#include "randpool.h"
#include "rsa.h"
#include "hex.h"
#include "files.h"
#include <iostream>


using namespace std;
using namespace CryptoPP;


#pragma comment(lib, "cryptlib.lib")


void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed);
string RSAEncryptString(const char *pubFilename, const char *seed, const char *message);
string RSADecryptString(const char *privFilename, const char *ciphertext);
RandomPool & GlobalRNG();


void main()
{
char priKey[128] = {0};
char pubKey[128] = {0};
char seed[1024] = {0};


//生成RSA密钥对
strcpy(priKey, "pri"); //生成的私钥文件
strcpy(pubKey, "pub"); //生成的公钥文件
strcpy(seed, "seed");
GenerateRSAKey(1024, priKey, pubKey, seed);


//RSA加解密
char message[1024] = {0};
cout<<"Origin Text:\t"<<"Hello World!"<<endl<<endl;
strcpy(message, "Hello World!");
string encryptedText = RSAEncryptString(pubKey, seed, message); //RSA加密
cout<<"Encrypted Text:\t"<<encryptedText<<endl<<endl;
string decryptedText = RSADecryptString(priKey, encryptedText.c_str()); //RSA解密
cout<<"Decrypted Text:\t"<<decryptedText<<endl;
}


//生成RSA密钥对
void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed)
{
RandomPool randPool;
randPool.Put((byte *)seed, strlen(seed));


RSAES_OAEP_SHA_Decryptor priv(randPool, keyLength);
HexEncoder privFile(new FileSink(privFilename));
priv.DEREncode(privFile);
privFile.MessageEnd();


RSAES_OAEP_SHA_Encryptor pub(priv);
HexEncoder pubFile(new FileSink(pubFilename));
pub.DEREncode(pubFile);
pubFile.MessageEnd();


}


//RSA加密
string RSAEncryptString(const char *pubFilename, const char *seed, const char *message)
{
FileSource pubFile(pubFilename, true, new HexDecoder);
RSAES_OAEP_SHA_Encryptor pub(pubFile);


RandomPool randPool;
randPool.Put((byte *)seed, strlen(seed));


string result;
StringSource(message, true, new PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(result))));
return result;
}


//RSA解密
string RSADecryptString(const char *privFilename, const char *ciphertext)
{
FileSource privFile(privFilename, true, new HexDecoder);
RSAES_OAEP_SHA_Decryptor priv(privFile);


string result;
StringSource(ciphertext, true, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), priv, new StringSink(result))));
return result;
}


//定义全局的随机数池
RandomPool & GlobalRNG()
{
static RandomPool randomPool;
return randomPool;
}

参考:

http://hi.baidu.com/ccse/blog/item/27118a950fce44017bf480b2.html

http://security.zdnet.com.cn/security_zone/2009/0224/1349364.shtml

http://wenku.baidu.com/view/c8a837ea81c758f5f61f6778.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值