http://www.cnblogs.com/AloneSword/p/3326750.html
RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。
解密者拥有私钥,并且将由私钥计算生成的公钥发布给加密者。加密都使用公钥进行加密,并将密文发送到解密者,解密者用私钥解密将密文解码为明文。
以甲要把信息发给乙为例,首先确定角色:甲为加密者,乙为解密者。首先由乙随机确定一个KEY,称之为密匙,将这个KEY始终保存在机器B中而不发出来;然后,由这个 KEY计算出另一个KEY,称之为公匙。这个公钥的特性是几乎不可能通过它自身计算出生成它的私钥。接下来通过网络把这个公钥传给甲,甲收到公钥后,利用公钥对信息加密,并把密文通过网络发送到乙,最后乙利用已知的私钥,就对密文进行解码了。以上就是RSA算法的工作流程。
算法实现过程为:
1. 随意选择两个大的质数p和q,p不等于q,计算N=pq。
2. 根据欧拉函数,不大于N且与N互质的整数個数為(p-1)(q-1)。
3. 选择一个整数e与(p-1)(q-1)互质,并且e小于(p-1)(q-1)。
4. 用以下这个公式计算d:d× e ≡ 1 (mod (p-1)(q-1))。
5. 将p和q的记录销毁。
以上内容中,(N,e)是公钥,(N,d)是私钥。
下面讲解RSA算法的应用。
RSA的公钥和私钥是由KeyPairGenerator生成的,获取KeyPairGenerator的实例后还需要设置其密钥位数。设置密钥位数越高,加密过程越安全,一般使用1024位。如下代码:
[代码]java代码:
1 |
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA); |
3 |
keyPairGen.initialize( 1024 ); |
公钥和私钥可以通过KeyPairGenerator执行generateKeyPair()后生成密钥对KeyPair,通过KeyPair.getPublic()和KeyPair.getPrivate()来获取。如下代码:
[代码]java代码:
1 |
// 动态生成密钥对,这是当前最耗时的操作,一般要2s以上。 |
2 |
KeyPair keyPair = keyPairGen.generateKeyPair(); |
4 |
PublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); |
6 |
PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); |
7 |
byte [] publicKeyData = publicKey.getEncoded(); |
8 |
byte [] privateKeyData = publicKey.getEncoded(); |
公钥和私钥都有它们自己独特的比特编码,可以通过getEncoded()方法获取,返回类型为byte[]。通过byte[]可以再度将公钥或私钥还原出来。具体代码如下:
[代码]java代码:
01 |
// 通过公钥byte[]将公钥还原,适用于RSA算法 |
02 |
public static PublicKey getPublicKey( byte [] keyBytes) throws |
03 |
NoSuchAlgorithmException,InvalidKeySpecException { |
04 |
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); |
05 |
KeyFactory keyFactory = KeyFactory.getInstance( "RSA" ); |
06 |
PublicKey publicKey = keyFactory.generatePublic(keySpec); |
09 |
// 通过私钥byte[]将公钥还原,适用于RSA算法 |
10 |
public static PrivateKey getPrivateKey( byte [] keyBytes) throws |
11 |
NoSuchAlgorithmException,InvalidKeySpecException { |
12 |
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); |
13 |
KeyFactory keyFactory = KeyFactory.getInstance( "RSA" ); |
14 |
PrivateKey privateKey = keyFactory.generatePrivate(keySpec); |
在上文讲到的RSA算法实现过程中提到(N,e)是公钥,(N,d)是私钥。既然已经获取到了PublicKey和PrivateKey了,那如何取到N、e、d这三个值呢。要取到这三个值,首先要将PublicKey和PrivateKey强制转换成RSAPublicKey和RSAPrivateKey。共同的N值可以通过getModulus()获取。执行RSAPublicKey.getPublicExponent()可以获取到公钥中的e值,执行RSAPrivateKey.getPrivateExponent()可以获取私钥中的d值。这三者返回类型都是BigInteger。代码如下:
[代码]java代码:
02 |
public static void printPublicKeyInfo(PublicKey key){ |
03 |
RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; |
04 |
Log.d(MainActivity.TAG, "RSAPublicKey:" ); |
05 |
Log.d(MainActivity.TAG, "Modulus.length=" + |
06 |
rsaPublicKey.getModulus().bitLength()); |
07 |
Log.d(MainActivity.TAG, "Modulus=" + |
08 |
rsaPublicKey.getModulus().toString()); |
09 |
Log.d(MainActivity.TAG, "PublicExponent.length=" + |
10 |
rsaPublicKey.getPublicExponent().bitLength()); |
11 |
Log.d(MainActivity.TAG, "PublicExponent=" + |
12 |
rsaPublicKey.getPublicExponent().toString()); |
16 |
public static void printPublicKeyInfo(PrivateKey key){ |
17 |
RSAPrivateKey rsaPublicKey = (RSAPrivateKey) privateKey; |
18 |
Log.d(MainActivity.TAG, "RSAPrivateKey:" ); |
19 |
Log.d(MainActivity.TAG, "Modulus.length=" + |
20 |
rsaPrivateKey.getModulus().bitLength()); |
21 |
Log.d(MainActivity.TAG, "Modulus=" + |
22 |
rsaPrivateKey.getModulus().toString()); |
23 |
Log.d(MainActivity.TAG, "PublicExponent.length=" + |
24 |
rsaPrivateKey.getPrivateExponent().bitLength()); |
25 |
Log.d(MainActivity.TAG, "PublicExponent=" + |
26 |
rsaPrivateKey.getPrivateExponent().toString()); |
由于程序中动态生成KeyPair对明文加密后生成的密文是不可测的,所以在实际开发中通常在生成一个KeyPair后将公钥和私钥的N、e、d这三个特征值记录下来,在真实的开发中使用这三个特征值再去将PublicKey和PrivateKey还原出来。还原方法如下:
[代码]java代码:
02 |
public static PublicKey getPublicKey(String modulus, String |
04 |
throws NoSuchAlgorithmException, InvalidKeySpecException { |
05 |
BigInteger bigIntModulus = new BigInteger(modulus); |
06 |
BigInteger bigIntPrivateExponent = new BigInteger(publicExponent); |
07 |
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, |
08 |
bigIntPrivateExponent); |
09 |
KeyFactory keyFactory = KeyFactory.getInstance( "RSA" ); |
10 |
PublicKey publicKey = keyFactory.generatePublic(keySpec); |
15 |
public static PrivateKey getPrivateKey(String modulus, String |
17 |
throws NoSuchAlgorithmException, InvalidKeySpecException { |
18 |
BigInteger bigIntModulus = new BigInteger(modulus); |
19 |
BigInteger bigIntPrivateExponent = new BigInteger(privateExponent); |
20 |
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(bigIntModulus, |
21 |
bigIntPrivateExponent); |
22 |
KeyFactory keyFactory = KeyFactory.getInstance( "RSA" ); |
23 |
PrivateKey privateKey = keyFactory.generatePrivate(keySpec); |
公钥和私钥都具备后,就可以使用加解密的工具类javax.crypto.Cipher对明文和密文进行处理了。与所有的引擎类一样,可以通过调用Cipher类中的getInstance(String transformation)静态工厂方法得到Cipher对象。该方法中的参数描述了由指定输入产生输出所进行的操作或操作集合,可以是下列两种形式之一:“algorithm/mode/padding”或“algorithm”。例如下面的例子就是有效的transformation形式:"DES/CBC/PKCS5Padding"或"DES"。如果没有指定模式或填充方式,就使用特定提供者指定的默认模式或默认填充方式。
Cipher的加密和解密方式所调用的方法和过程都一样,只是传参不同的区别。如下代码:
[代码]java代码:
2 |
cipher.init(mode, key); |
4 |
byte [] dataResult = cipher.doFinal(input); |
Cipher.init(mode, key)方法中MODE指加密或解密模式,值为Cipher.ENCRYPT_MODE或Cipher.DECRYPT_MODE,参数key在加密时传入PublicKey,在解密时以PrivateKey传入。Cipher.doFinal(byte[] data)则是将待编码数据传入后并返回编码结果。为了将编码结果转为可读字符串,通常最后还使用BASE 64算法对最终的byte[]数据编码后显示给开发者。
Demo运行效果如下图所示:
图17-4 使用动态生成的公钥和私钥进行RSA加密
图17-5 使用预设的N、e、d值进行RSA加密
- (转)RSA算法原理(二)
作者: 阮一峰 日期: 2013年7月 4日 上一次,我介绍了一些数论知识. 有了这些知识,我们就可以看懂RSA算法.这是目前地球上最重要的加密算法. 六.密钥生成的步骤 我们通过一个例子,来理解 ...
- (转) RSA算法原理(一)
最近用到了RSA加密算法,虽然有现成的,但是想看看它的原理,翻到此文,感觉写得很好,通俗易懂,转了. 作者: 阮一峰 日期: 2013年6月27日 如果你问我,哪一种算法最重要? 我可能会回答&q ...
- RSA算法基础详解
. 首页 博客园 联系我 前言:在RSA诞生之前. RSA算法. 质数与互质数. 模运算. 同余. 欧拉函数. 欧拉定理与模反元素. 真实的例子. 计算密钥. 密钥组成与加解密公式. 安全性. 一点感 ...
- SSH原理与运用(一)和(二):远程登录 RSA算法原理(一)和(二)
SSH原理与运用(一)和(二):远程登录 RSA算法原理(一)和(二) http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html ht ...
- 阮一峰:RSA算法原理(一)
今天看到一篇好文章,关于加密算法,收藏了觉得不过瘾,还是自己贴一遍,也能加深一下印象. 原文链接:http://www.ruanyifeng.com/blog/2013/06/rsa_algorith ...
- (转)RSA算法原理
RSA算法原理(二) 作者: 阮一峰 日期: 2013年7月 4日 上一次,我介绍了一些数论知识. 有了这些知识,我们就可以看懂RSA算法.这是目前地球上最重要的加密算法. 六.密钥生成的步骤 我 ...
- RSA算法解析
RSA算法原理(一) 如果你问我,哪一种算法最重要? 我可能会回答"公钥加密算法". 因为它是计算机通信安全的基石,保证了加密数据不会被破解.你可以想象一下,信用卡交易被破解的后果 ...
- RSA算法原理(二)
上一次,我介绍了一些数论知识. 有了这些知识,我们就可以看懂RSA算法.这是目前地球上最重要的加密算法. 六.密钥生成的步骤 我们通过一个例子,来理解RSA算法.假设爱丽丝要与鲍勃进行加密通信,她该怎 ...
- RSA算法原理(一)
如果你问我,哪一种算法最重要? 我可能会回答"公钥加密算法". 因为它是计算机通信安全的基石,保证了加密数据不会被破解.你可以想象一下,信用卡交易被破解的后果. 进入正题之前,我先 ...
随机推荐
- SQL2008-删除时间字段重复的方法
ID EMAgitation_ID YieldDateTime 1 2 2012-02-11 10:18:54.0002 2 ...
- Keil MDK 无法设置断点【worldsing】
要解决一个问题就怕不知道怎么搜索,或是别人没有遇到过: 同样碰到Keil MDK Debug调试无法设置断点问题,首先来问百度,GOOGLE,一下是我搜索到的结果: 1.keil 不能设置断点,每 ...
- 射频识别技术漫谈(9)——动物标签HDX【worldsing笔记】
半双工(HDX,Half Duplex)技术是ISO11784/11785中规定的另一种标签与读写器之间的通讯方式.读写器先打开射频场对标签充电以激活标签,然后关闭磁场,标签在读写器磁场关闭的情况下向 ...
- 【Stage3D学习笔记续】山寨Starling(九):上下文丢失处理方法
Stage3D在运行中是存在随时会丢失上下文的尴尬情况. 渲染内容丢失的问题本身就说明是因为丢失了Context3D对象.出现此问题的原因很多,通常还不是因为Stage3D应用.比如在win7系统中, ...
- ios引导页 设定以及 图片尺寸
iphone的屏幕尺寸有着几种: iphone 4/4s: 3.5 寸 分辨率:640X960 高宽比 640/960 = 1.5 iphone 5/5c/5s:4 寸 分辨率:640X1136 ...
- Android设计模式—策略模式
1.策略模式概念 定义一系列算法,把他们独立封装起来,并且这些算法之间可以相互替换.策略模式主要是管理一堆有共性的算法,客户端可以根据需要,很快切换这些算法,并且保持可扩展性. 策略模式的本质:分离算 ...
- 授予普通域用户远程桌面连接DC/客户端权限
普通域用户通过远程桌面登录DC: 1)将该用户加入到 Remote Desktop Users 组中
- Project Management - 2) Estimate Your Work
1. Delphi估算 1) 项目经理召集小组成员,就项目有关事宜向大家进行阐述. 2)大家提出各种问题,然后进行分配任务. 每个人写下自己的任务列表和时间估算. 3)项目经理收集好任务之后进行复查, ...
- Mysql 5.5 replication 多数据库主从备份Master-Slave配置总结
配置Mysql server 5.5 的双机备份,也就是master-slave模式.本例子还是一个多database复制的情况. 现在有两个database在同一台mysql server,也就是m ...
- [AngularJS] Accessible Button Events
Often buttons need to be handled by JavaScript, and if done improperly it can lead to accessibility ...