[安全] 关于 RSA 算法的原理与实践

长平狐 发布于 2012/11/19 15:10
阅读 844
收藏 0

当代信息网络发展至今,覆盖面已经非常广泛,广大用户使用这个互联网络来分享信息,搜索资料,进行商业交易等等,可以说是无处不在,也因为这样,这个领域中的信息安全也就变得越来越重要。在这个背景下 “公匙密码学” 也就应运而生,很显然的是,随着信息网络越来越深入到人们的生活和商务金融领域,这门学科也将变得越来越重要。以下石头将会就这个命题展开,首先让我们来看看 “公钥密码学概述” (摘自网络):

公开密钥密码算法的提出是整个密码学历史上最大的而且也许是最唯一真正的变革。从最初一直到现代,几乎所有密码系统都建立在基本的替代和置换工具的基础上。在用了数千年的本质上可以手算完成的算法之后,常规的密码学随着转轮加密/解密机的发展才出现了一个重大进步。机电式变码旋转软件使得极其复杂的密码系统被研制出来。有了计算机后,更加复杂的系统被设计出来。但是不管是转轮机还是后来的DES(数据加密标准),虽然代表了重要的进展,却仍然依赖于替代和置换这样的基本工具。公钥密码学则与以前的所有方法都截然不同。一方面公开密钥算法基于数学函数而不是替代和置换,更重要的是,公开密钥密码学是非对称的,它用到两个不同的密钥,而对称的常规加密则只使用一个密钥。使用两个密钥对于保密通信,密钥分配和鉴别等领域都有着深远的影响。

对于公钥密码加密有几个误解:
误解一、公开密钥加密在防范密码分析上比常规加密更加安全。
[解释] 事实上,任何加密方案的安全性都依赖于密钥的长度和破译密码所包含的计算工作量。从抗击密码分析的角度讲,无论常规还是公开密钥加密原则上都没有比对方优越的地方。
误解二、公开密钥加密是一个使得常规加密已经过时的通用技术。
[解释] 事实上,由于当前公开密钥加密在计算上的巨大开销,在可以预见的未来常规加密并不会被抛弃。目前大家几乎普遍接受的观点是公开密钥密码算法只限于密钥管理和数字签名等应用。
误解三、与使用常规加密时涉及密钥分配中心的相当繁琐的握手过程相比,使用公开密钥加密后密钥分配就变的非常简单。
[解释] 事实上,使用公开密钥加密仍然需要某种形式的协议,一般这会涉及到一个中心代理,而且整个过程比常规加密中的过程既不简单也不更有效。

目前存在两种密钥体制:对称密钥体制和非对称密钥体制。对称密钥体制就是加密和解密用同一个密钥。这很好理解,相当于你用你家的钥匙既可以锁上你家的门,也可以打开你家的门。非对称密钥体制就是加密和解密不是同一个密钥。也就是说一个密钥所加密的数据用另一个密钥解密。举个生活中的例子,类似于在机场、火车站、超市以及很多其他公共场所看到的非对称的存物箱。为了安全存储你的财物,你把它们放入存物箱并且投入钱币锁上它。就如同你的住宅钥匙锁上大门一样,钱币锁上了存物箱---在某种意义上,你的钱币就是密钥。锁上门后,你得到另外一把钥匙---也许是一把真正的钥匙;也许只是一张写有号码的纸条。要开启存物箱,你就要使用该钥匙或在键盘上输入号码。而这个时候,你投入多少钱币也是打不开存物箱的。类似地,我们可以产生一个密码算法,其中一个密钥用来加密数据,另一个用来解密。这个模型的另一说法就是公钥密码学。要加密和解密数据,两个密钥都需要使用,所以其中一个可以公开而不会危害安全性。这个密钥就是公钥。另一个则称之为私钥。我们用公钥加密数据,用私钥解密数据。就好象例子中的任何人都知道用钱币(公钥)锁上存物箱,但仍然打不开存物箱。只有拥有钥匙或写有号码的纸条(私钥)的人才能打开存物箱。

1976年后,提出了多种公开密钥算法,其中许多是不安全的。而那些被视为安全的算法,有许多却不实用,要么密钥太大,要么密文远大于明文。只有少数几个算法既安全又实用。其中有三种算法可以很好的用于加密和数字签名:RSA、ElGamal 和Rabin。不过它们都很慢。它们加密和解密速度比对称算法要慢的多,通常是太慢以致无法用于许多快速数据加密。基于这点考虑,很多时候使用混合密码系统。使用带随机会话密钥的对称算法来加密消息,使用公开密钥算法来加密随机会话密钥。

到这里,大家应该对公匙密码学的背景有一定了解了吧,而在具体的应用中我们应该怎么适当的使用这两种加密体制的算法呢?石头认为,在大部分情况下我们应该选用计算效率比较高的对称密匙算法,但是在某些特殊情况下,我们应该使用非对称密匙算法,比如 HTTPS 加密协议,SSH 无密码信任机制等,这里石头要说说另一个 “特殊情况” 那就是 Javascript 加密,由于 Javascript 代码是公开的,如果使用一般的加密算法,很可能出现算法或者密匙泄露的问题,在这种情况下对于一些敏感数据,我们就需要使用公匙算法了,当然对于一般的商务站点也可以直接使用 HTTPS 加密,但是如果只是对一小部分的数据需要加密,使用 HTTPS 明显效率要差得多。以下,石头就以一个实例来说明这个策略的原理与应用的部署。

如果大家有研究过 QQ 邮箱的登录流程,大家可能就会注意到这里他们就运用到 Javascript 端的 RSA 加密策略,目前石头为一家电子商务网站也部署了类似的一套应用,后端使用的是 PHP,基本解决了一些敏感数据的防劫持功能,废话不多说,看看部署步骤:

1、 下载 Javascript 的 RSA 加密库:我们这里使用的是斯坦福大学某位高人写的一套 Pure Javascript 的 RSA 加密库,具体地址为 http://www-cs-students.stanford.edu/~tjw/jsbn/ ,目前石头把这个库集合起来,传到 Hush Framework 上了,大家可以到以下地址下载:https://hush-framework.googlecode.com/svn/trunk/hush-lib/Hush/Crypt/Rsa/openssl.js

2、 使用 openssl 生成服务器端的证书和公私匙:server.crt 和 server.key

# CA.sh -newcert
# ...
# mv newkey.pem server.key
# mv newcert.pem server.crt
# ...
# openssl rsa -in server.key -noout -modulus
# (得到公匙,拷贝复制)


3、 我们把公匙发给客户端的 Javascript 加密,加密参考代码如下:
...
function rsa_encrypt (Value, PublicKey) {
    var RSA = new RSAKey();
    RSA.setPublic(PublicKey, '10001');
    return RSA.encrypt(encodeURIComponent(Value));
}
...
这里我们可以给函数传入需要加密的值和公匙,返回加密过的字符串传给服务器端。

4、 服务器端 PHP 调用 openssl 方法利用保存在服务器端的私钥进行解密,参考代码如下:
...
public function rsa_decrypt ($string, $priv_key) {
    $decrypt = '';
    $encrypt = pack("H*", $string);
    openssl_private_decrypt($encrypt, $decrypt, $priv_key);
    return $decrypt;
}
...
这里我们给函数传入加密过的字符串和私钥,就可以返回解密后的字符串数据了。

至此,整个实例介绍基本完毕。这里需要特别注意一点,以上实例生成的密匙可以加解密的最大字符串长度是:1024/8-11=117,如果您需要加密更长的字符串请使用 2048 或者以上位数的 RSA。 以下是 RSA 的算法概述,有兴趣的朋友可以参考:

找两素数p和q
取n=p*q
取t=(p-1)*(q-1)
取任何一个数e,要求满足e<t并且e与t互素(就是最大公因数为1)
取d*e%t==1

这样最终得到三个数: n  d  e

设消息为数M (M <n)
设c=(M**d)%n就得到了加密后的消息c
设m=(c**e)%n则 m == M,从而完成对c的解密。
注:**表示次方,上面两式中的d和e可以互换。

在对称加密中:
n d两个数构成公钥,可以告诉别人;
n e两个数构成私钥,e自己保留,不让任何人知道。
给别人发送的信息使用e加密,只要别人能用d解开就证明信息是由你发送的,构成了签名机制。
别人给你发送信息时使用d加密,这样只有拥有e的你能够对其解密。

rsa的安全性在于对于一个大数n,没有有效的方法能够将其分解
从而在已知n d的情况下无法获得e;同样在已知n e的情况下无法
求得d。

RSA简洁幽雅,但计算速度比较慢,通常加密中并不是直接使用RSA 来对所有的信息进行加密,
最常见的情况是随机产生一个对称加密的密钥,然后使用对称加密算法对信息加密,之后用
RSA对刚才的加密密钥进行加密。

最后需要说明的是,当前小于1024位的N已经被证明是不安全的
自己使用中不要使用小于1024位的RSA,最好使用2048位的。


原文链接:http://blog.csdn.net/shagoo/article/details/5736858
加载中
返回顶部
顶部