RSA算法使用介绍
2015-12-03 17:21
190 查看
原文地址:http://www.devdiv.com/rsa_-blog-20-11254.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位。如下代码:
公钥和私钥可以通过KeyPairGenerator执行generateKeyPair()后生成密钥对KeyPair,通过KeyPair.getPublic()和KeyPair.getPrivate()来获取。如下代码:
公钥和私钥都有它们自己独特的比特编码,可以通过getEncoded()方法获取,返回类型为byte[]。通过byte[]可以再度将公钥或私钥还原出来。具体代码如下:
在上文讲到的RSA算法实现过程中提到(N,e)是公钥,(N,d)是私钥。既然已经获取到了PublicKey和PrivateKey了,那如何取到N、e、d这三个值呢。要取到这三个值,首先要将PublicKey和PrivateKey强制转换成RSAPublicKey和RSAPrivateKey。共同的N值可以通过getModulus()获取。执行RSAPublicKey.getPublicExponent()可以获取到公钥中的e值,执行RSAPrivateKey.getPrivateExponent()可以获取私钥中的d值。这三者返回类型都是BigInteger。代码如下:
由于程序中动态生成KeyPair对明文加密后生成的密文是不可测的,所以在实际开发中通常在生成一个KeyPair后将公钥和私钥的N、e、d这三个特征值记录下来,在真实的开发中使用这三个特征值再去将PublicKey和PrivateKey还原出来。还原方法如下:
公钥和私钥都具备后,就可以使用加解密的工具类javax.crypto.Cipher对明文和密文进行处理了。与所有的引擎类一样,可以通过调用Cipher类中的getInstance(Stringtransformation)静态工厂方法得到Cipher对象。该方法中的参数描述了由指定输入产生输出所进行的操作或操作集合,可以是下列两种形式之一:“algorithm/mode/padding”或“algorithm”。例如下面的例子就是有效的transformation形式:"DES/CBC/PKCS5Padding"或"DES"。如果没有指定模式或填充方式,就使用特定提供者指定的默认模式或默认填充方式。
Cipher的加密和解密方式所调用的方法和过程都一样,只是传参不同的区别。如下代码:
Cipher.init(mode,key)方法中MODE指加密或解密模式,值为Cipher.ENCRYPT_MODE或Cipher.DECRYPT_MODE,参数key在加密时传入PublicKey,在解密时以PrivateKey传入。Cipher.doFinal(byte[]data)则是将待编码数据传入后并返回编码结果。为了将编码结果转为可读字符串,通常最后还使用BASE64算法对最终的byte[]数据编码后显示给开发者。
Demo运行效果如下图所示:
图17-4使用动态生成的公钥和私钥进行RSA加密
图17-5使用预设的N、e、d值进行RSA加密
Demo源代码下载:Code_Test.rar
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 ); |
[代码]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(); |
[代码]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 | } |
[代码]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 | } |
[代码]java代码:
01 | // 使用N、e值还原公钥 |
02 | public static PublicKey getPublicKey(Stringmodulus,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(Stringmodulus,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 | } |
Cipher的加密和解密方式所调用的方法和过程都一样,只是传参不同的区别。如下代码:
[代码]java代码:
1 | // 编码前设定编码方式及密钥 |
2 | cipher.init(mode, key); |
3 | // 传入编码数据并返回编码结果 |
4 | byte [] |
Demo运行效果如下图所示:
图17-4使用动态生成的公钥和私钥进行RSA加密
图17-5使用预设的N、e、d值进行RSA加密
Demo源代码下载:
相关文章推荐
- OpenSSL编程之RSA
- 每 172 个活动 RSA 证书中就有一个容易受到攻击
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例