RSA算法使用介绍

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

时间: 2024-10-06 22:51:13

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

关于RSA算法的介绍

今天看见了一个个人博客关于计算机,非常简洁的介绍了RSA算法的来历,和用到的一些数论只是. http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_two.html

非对称加密——RSA算法工具类

关于RSA算法的介绍网上一大堆,一句话就是牛B. package com.demo; import org.springframework.util.StringUtils; import javax.crypto.Cipher; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.secur

RSA算法(一)

转载:http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html 作者: 阮一峰 日期: 2013年6月27日 如果你问我,哪一种算法最重要? 我可能会回答"公钥加密算法". 因为它是计算机通信安全的基石,保证了加密数据不会被破解.你可以想象一下,信用卡交易被破解的后果. 进入正题之前,我先简单介绍一下,什么是"公钥加密算法". 一.一点历史 1976年以前,所有的加密方法都是同一种模式: (

RSA算法(二)

转载:http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html 作者: 阮一峰 日期: 2013年7月 4日 上一次,我介绍了一些数论知识. 有了这些知识,我们就可以看懂RSA算法.这是目前地球上最重要的加密算法. 六.密钥生成的步骤 我们通过一个例子,来理解RSA算法.假设爱丽丝要与鲍勃进行加密通信,她该怎么生成公钥和私钥呢? 第一步,随机选择两个不相等的质数p和q. 爱丽丝选择了61和53.(实际应用中,这两个质数越

RSA算法Java的简单实现

RSA简介 RSA算法据说是目前地球上最重要的加密算法.维基百科是这么介绍的:"对极大整数做因数分解的难度决定了RSA算法的可靠性.换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠.假如有人找到一种快速因数分解的算法,那么RSA的可靠性就会极度下降.但找到这样的算法的可能性是非常小的.今天只有短的RSA密钥才可能被暴力破解.到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式.只要密钥长度足够长,用RSA加密的信息实际上是不能被解破的." 看上去很神奇是吧,其实在学习网络

RSA算法基础详解

前言:在RSA诞生之前 RSA算法是最重要算法之一 它是计算机通信安全的基石,安全可靠 只要有计算机网络的地方,就有RSA算法 在它诞生之前,即1976年以前,加解密信息使用同一种规则 甲方选择某一种加密规则,对信息进行加密: 乙方使用同一种规则,对信息进行解密. 虽然理论上,只要加解密“规则”(即“密钥”)足够复杂,这种方式也可安全的传递信息 但这种方法最大的弱点就是,密钥在传递的过程中易被泄露 这种加密和解密使用同样规则的方法,被称为“对称加密算法” RSA算法 倘若在加解密信息的过程中,能

安全体系(二)——RSA算法详解

本文主要讲述RSA算法使用的基本数学知识.秘钥的计算过程以及加密和解密的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 1.概述 RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.1987年首次公布,当时他们三人都在麻省理工学院工作.RSA算法以他们三人姓氏开头字母命名. RSA是目前最有影响力的公钥加密

RSA算法记录----摘抄

RSA算法原理(一) "公钥加密算法". 因为它是计算机通信安全的基石,保证了加密数据不会被破解.你可以想象一下,信用卡交易被破解的后果. 进入正题之前,我先简单介绍一下,什么是"公钥加密算法". 一.一点历史 1976年以前,所有的加密方法都是同一种模式: (1)甲方选择某一种加密规则,对信息进行加密: (2)乙方使用同一种规则,对信息进行解密. 由于加密和解密使用同样规则(简称"密钥"),这被称为"对称加密算法"(Symm

ios下使用RSA算法加密与java后台解密配合demo

首先了解一下几个相关概念,以方便后面遇到的问题的解决: 原网址:http://blog.csdn.net/jinglijun/article/details/7770315RSA算法:1977年由Ron Rivest.Adi Shamirh和LenAdleman发明的,RSA就是取自他们三个人的名字.算法基于一个数论:将两个大素数相乘非常容易,但要对这个乘积的结果进行因式分解却非常困难,因此可以把乘积公开作为公钥.该算法能够抵抗目前已知的所有密码攻击.RSA算法是一种非对称算法,算法需要一对密钥