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);
2 // 密钥位数
3 keyPairGen.initialize(1024);
 
        公钥和私钥可以通过KeyPairGenerator执行generateKeyPair()后生成密钥对KeyPair,通过KeyPair.getPublic()和KeyPair.getPrivate()来获取。如下代码:
 

[代码]java代码:

1 // 动态生成密钥对,这是当前最耗时的操作,一般要2s以上。
2 KeyPair keyPair = keyPairGen.generateKeyPair();
3 // 公钥
4 PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
5 // 私钥
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);
07     return publicKey;
08 }
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);
15     return privateKey;
16 }
        在上文讲到的RSA算法实现过程中提到(N,e)是公钥,(N,d)是私钥。既然已经获取到了PublicKey和PrivateKey了,那如何取到N、e、d这三个值呢。要取到这三个值,首先要将PublicKey和PrivateKey强制转换成RSAPublicKey和RSAPrivateKey。共同的N值可以通过getModulus()获取。执行RSAPublicKey.getPublicExponent()可以获取到公钥中的e值,执行RSAPrivateKey.getPrivateExponent()可以获取私钥中的d值。这三者返回类型都是BigInteger。代码如下:
 

[代码]java代码:

01 // 打印公钥信息
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());
13 }
14  
15 // 打印私钥信息
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());
27 }
 
        由于程序中动态生成KeyPair对明文加密后生成的密文是不可测的,所以在实际开发中通常在生成一个KeyPair后将公钥和私钥的N、e、d这三个特征值记录下来,在真实的开发中使用这三个特征值再去将PublicKey和PrivateKey还原出来。还原方法如下:
 

[代码]java代码:

01 // 使用N、e值还原公钥
02 public static PublicKey getPublicKey(String modulus, String
03 publicExponent)
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);
11     return publicKey;
12 }
13  
14 // 使用N、d值还原公钥
15 public static PrivateKey getPrivateKey(String modulus, String
16 privateExponent)
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);
24     return privateKey;
25 }
 
        公钥和私钥都具备后,就可以使用加解密的工具类javax.crypto.Cipher对明文和密文进行处理了。与所有的引擎类一样,可以通过调用Cipher类中的getInstance(String transformation)静态工厂方法得到Cipher对象。该方法中的参数描述了由指定输入产生输出所进行的操作或操作集合,可以是下列两种形式之一:“algorithm/mode/padding”或“algorithm”。例如下面的例子就是有效的transformation形式:"DES/CBC/PKCS5Padding"或"DES"。如果没有指定模式或填充方式,就使用特定提供者指定的默认模式或默认填充方式。
 
        Cipher的加密和解密方式所调用的方法和过程都一样,只是传参不同的区别。如下代码:
 

[代码]java代码:

1 // 编码前设定编码方式及密钥
2 cipher.init(mode, key);
3 // 传入编码数据并返回编码结果
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加密
 
Demo源代码下载:Code_Test.rar

RSA算法使用介绍的更多相关文章

  1. (转)RSA算法原理(二)

      作者: 阮一峰 日期: 2013年7月 4日 上一次,我介绍了一些数论知识. 有了这些知识,我们就可以看懂RSA算法.这是目前地球上最重要的加密算法. 六.密钥生成的步骤 我们通过一个例子,来理解 ...

  2. (转) RSA算法原理(一)

    最近用到了RSA加密算法,虽然有现成的,但是想看看它的原理,翻到此文,感觉写得很好,通俗易懂,转了.   作者: 阮一峰 日期: 2013年6月27日 如果你问我,哪一种算法最重要? 我可能会回答&q ...

  3. RSA算法基础详解

    . 首页 博客园 联系我 前言:在RSA诞生之前. RSA算法. 质数与互质数. 模运算. 同余. 欧拉函数. 欧拉定理与模反元素. 真实的例子. 计算密钥. 密钥组成与加解密公式. 安全性. 一点感 ...

  4. SSH原理与运用(一)和(二):远程登录 RSA算法原理(一)和(二)

    SSH原理与运用(一)和(二):远程登录  RSA算法原理(一)和(二) http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html ht ...

  5. 阮一峰:RSA算法原理(一)

    今天看到一篇好文章,关于加密算法,收藏了觉得不过瘾,还是自己贴一遍,也能加深一下印象. 原文链接:http://www.ruanyifeng.com/blog/2013/06/rsa_algorith ...

  6. (转)RSA算法原理

    RSA算法原理(二)   作者: 阮一峰 日期: 2013年7月 4日 上一次,我介绍了一些数论知识. 有了这些知识,我们就可以看懂RSA算法.这是目前地球上最重要的加密算法. 六.密钥生成的步骤 我 ...

  7. RSA算法解析

    RSA算法原理(一) 如果你问我,哪一种算法最重要? 我可能会回答"公钥加密算法". 因为它是计算机通信安全的基石,保证了加密数据不会被破解.你可以想象一下,信用卡交易被破解的后果 ...

  8. RSA算法原理(二)

    上一次,我介绍了一些数论知识. 有了这些知识,我们就可以看懂RSA算法.这是目前地球上最重要的加密算法. 六.密钥生成的步骤 我们通过一个例子,来理解RSA算法.假设爱丽丝要与鲍勃进行加密通信,她该怎 ...

  9. RSA算法原理(一)

    如果你问我,哪一种算法最重要? 我可能会回答"公钥加密算法". 因为它是计算机通信安全的基石,保证了加密数据不会被破解.你可以想象一下,信用卡交易被破解的后果. 进入正题之前,我先 ...

随机推荐

  1. 第十三章、学习 Shell Scripts 简单的 shell script 练习

    简单的 shell script 练习 简单范例 对谈式脚本:变量内容由使用者决定 [root@www scripts]# vi sh02.sh #!/bin/bash # Program: # Us ...

  2. hdu 1595 find the longest of the shortest【最短路枚举删边求删除每条边后的最短路,并从这些最短路中找出最长的那条】

    find the longest of the shortest Time Limit: 1000/5000 MS (Java/Others)    Memory Limit: 32768/32768 ...

  3. hdu 2716 Message Decowding

    Message Decowding Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  4. [C语言 - 14] 进制

    进制 二进制 int number = 0B1010; 没有二进制的输出格式   八进制     int number2 = 07613;     printf("number2 = %o\ ...

  5. C++学习笔记(八):函数重载、函数指针和函数对象

    函数重载 函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数.重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于 ...

  6. 设置 ubuntu ftp

    apt-get install后就是启动不了,ftp localhost connection refued 1. 关闭ubuntu防火墙 :  ufw disable 2. 还是不行,报 500 m ...

  7. 如何避免regionServer宕机

    为什么regionserver 和Zookeeper的session expired? 可能的原因有 1. 网络不好. 2. Java full GC, 这会block所有的线程.如果时间比较长,也会 ...

  8. systemd service

    Man page systemd.unit SYSTEMD.UNIT(5) systemd.unit SYSTEMD.UNIT(5) NAME systemd.unit - Unit configur ...

  9. ILSpy反编译工具的使用

    以前一直使用reflector来查看.net类库的一些信息,不过,自2011年2月份开始,reflector就开始转向收费软件了,所以爱好免费软件的开发者们转而开发自己的反编译软件.于是ILspy就因 ...

  10. BZOJ [ZJOI2008]泡泡堂BNB 贪心

    [ZJOI2008]泡泡堂BNB Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/proble ...