RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密算法。
RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
关于RSA算法的原理,这里就不再详加介绍,网上各种资源一大堆。下面就开始介绍RSA加密解密JAVA类的具体实现。
01 |
import java.security.MessageDigest; |
03 |
import sun.misc.BASE64Decoder; |
04 |
import sun.misc.BASE64Encoder; |
08 |
public static final String KEY_SHA= "SHA" ; |
09 |
public static final String KEY_MD5= "MD5" ; |
17 |
public static byte [] decryptBASE64(String key) throws Exception{ |
18 |
return ( new BASE64Decoder()).decodeBuffer(key); |
27 |
public static String encryptBASE64( byte [] key) throws Exception{ |
28 |
return ( new BASE64Encoder()).encodeBuffer(key); |
37 |
public static byte [] encryptMD5( byte [] data) throws Exception{ |
38 |
MessageDigest md5 = MessageDigest.getInstance(KEY_MD5); |
49 |
public static byte [] encryptSHA( byte [] data) throws Exception{ |
50 |
MessageDigest sha = MessageDigest.getInstance(KEY_SHA); |
先提供Coder编码类,该类封装了基本的Base64、md5和SHA加密解密算法。Java对这些算法的实现提供了很好的API封装,开发人员只需调用这些API就可很简单方便的实现数据的加密与解密。
下面提供RSA加密解密类,该类为Coder类子类,因为其中对RSA公私密钥的保存进行了一层Base64加密处理。
RSA加密解密类静态常量
1 |
public static final String KEY_ALGORTHM= "RSA" ; // |
2 |
public static final String SIGNATURE_ALGORITHM= "MD5withRSA" ; |
4 |
public static final String PUBLIC_KEY = "RSAPublicKey" ; //公钥 |
5 |
public static final String PRIVATE_KEY = "RSAPrivateKey" ; //私钥 |
RSA加密解密的实现,需要有一对公私密钥,公私密钥的初始化如下:
06 |
public static Map<String,Object> initKey() throws Exception{ |
07 |
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM); |
08 |
keyPairGenerator.initialize( 1024 ); |
09 |
KeyPair keyPair = keyPairGenerator.generateKeyPair(); |
12 |
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); |
14 |
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); |
16 |
Map<String,Object> keyMap = new HashMap<String, Object>( 2 ); |
17 |
keyMap.put(PUBLIC_KEY, publicKey); |
18 |
keyMap.put(PRIVATE_KEY, privateKey); |
从代码中可以看出密钥的初始化长度为1024位,密钥的长度越长,安全性就越好,但是加密解密所用的时间就会越多。而一次能加密的密文长度也与密钥的长度成正比。一次能加密的密文长度为:密钥的长度/8-11。所以1024bit长度的密钥一次可以加密的密文为1024/8-11=117bit。所以非对称加密一般都用于加密对称加密算法的密钥,而不是直接加密内容。对于小文件可以使用RSA加密,但加密过程仍可能会使用分段加密。
从map中获取公钥、私钥
07 |
public static String getPublicKey(Map<String, Object> keyMap) throws Exception{ |
08 |
Key key = (Key) keyMap.get(PUBLIC_KEY); |
09 |
return encryptBASE64(key.getEncoded()); |
18 |
public static String getPrivateKey(Map<String, Object> keyMap) throws Exception{ |
19 |
Key key = (Key) keyMap.get(PRIVATE_KEY); |
20 |
return encryptBASE64(key.getEncoded()); |
对于RSA产生的公钥、私钥,我们可以有两种方式可以对信息进行加密解密。私钥加密-公钥解密 和 公钥加密-私钥解密。
私钥加密
08 |
public static byte [] encryptByPrivateKey( byte [] data,String key) throws Exception{ |
10 |
byte [] keyBytes = decryptBASE64(key); |
12 |
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); |
13 |
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); |
14 |
Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); |
17 |
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); |
18 |
cipher.init(Cipher.ENCRYPT_MODE, privateKey); |
20 |
return cipher.doFinal(data); |
私钥解密
02 |
* 用私钥解密<span style="color:#000000;"></span> * @param data 加密数据 |
07 |
public static byte [] decryptByPrivateKey( byte [] data,String key) throws Exception{ |
09 |
byte [] keyBytes = decryptBASE64(key); |
11 |
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); |
12 |
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); |
13 |
Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); |
15 |
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); |
16 |
cipher.init(Cipher.DECRYPT_MODE, privateKey); |
18 |
return cipher.doFinal(data); |
公钥加密
08 |
public static byte [] encryptByPublicKey( byte [] data,String key) throws Exception{ |
10 |
byte [] keyBytes = decryptBASE64(key); |
12 |
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); |
13 |
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); |
14 |
Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); |
17 |
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); |
18 |
cipher.init(Cipher.ENCRYPT_MODE, publicKey); |
20 |
return cipher.doFinal(data); |
私钥加密
08 |
public static byte [] decryptByPublicKey( byte [] data,String key) throws Exception{ |
10 |
byte [] keyBytes = decryptBASE64(key); |
11 |
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); |
12 |
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); |
13 |
Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); |
16 |
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); |
17 |
cipher.init(Cipher.DECRYPT_MODE, publicKey); |
19 |
return cipher.doFinal(data); |
关于数字签名,先了解下何为数字签名。数字签名,就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。数字签名是非对称密钥加密技术与数字摘要技术的应用。简单地说,所谓数字签名就是附加在数据单元上的一些数据,或是对数据单元所作的密码变换。这种数据或变换允许数据单元的接收者用以确认数据单元的来源和数据单元的完整性并保护数据,防止被人(例如接收者)进行伪造。
数字签名的主要功能如下:
保证信息传输的完整性、发送者的身份认证、防止交易中的抵赖发生。
数字签名技术是将摘要信息用发送者的私钥加密,与原文一起传送给接收者。接收者只有用发送者的公钥才能解密被加密的摘要信息,然后用对收到的原文产生一个摘要信息,与解密的摘要信息对比。如果相同,则说明收到的信息是完整的,在传输过程中没有被修改,否则说明信息被修改过,因此数字签名能够验证信息的完整性。
数字签名是个加密的过程,数字签名验证是个解密的过程。
数字签名算法依靠公钥加密技术来实现的。在公钥加密技术里,每一个使用者有一对密钥:一把公钥和一把私钥。公钥可以自由发布,但私钥则秘密保存;还有一个要求就是要让通过公钥推算出私钥的做法不可能实现。
普通的数字签名算法包括三种算法:
1.密码生成算法;
2.标记算法;
3.验证算法。
通过RSA加密解密算法,我们可以实现数字签名的功能。我们可以用私钥对信息生成数字签名,再用公钥来校验数字签名,当然也可以反过来公钥签名,私钥校验。
私钥签名
04 |
* @param privateKey //私钥 |
08 |
public static String sign( byte [] data,String privateKey) throws Exception{ |
10 |
byte [] keyBytes = decryptBASE64(privateKey); |
11 |
//构造PKCS8EncodedKeySpec对象 |
12 |
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); |
14 |
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); |
16 |
PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec); |
18 |
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); |
19 |
signature.initSign(privateKey2); |
20 |
signature.update(data); |
22 |
return encryptBASE64(signature.sign()); |
公钥校验
09 |
public static boolean verify( byte [] data,String publicKey,String sign) throws Exception{ |
11 |
byte [] keyBytes = decryptBASE64(publicKey); |
12 |
//构造X509EncodedKeySpec对象 |
13 |
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); |
15 |
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); |
17 |
PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec); |
19 |
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); |
20 |
signature.initVerify(publicKey2); |
21 |
signature.update(data); |
23 |
return signature.verify(decryptBASE64(sign)); |
对于RSA如何加密文件、图片等信息,加密的信息又如何保存,怎样保存解密后的信息,以及操作过程中遇到的错误将如何处理,将在后面的文章中介绍给大家。
原文:http://www.360doc.com/content/14/0324/16/834950_363341045.shtml
- (转)RSA加密解密及数字签名Java实现
转:http://my.oschina.net/jiangli0502/blog/171263?fromerr=hc4izFe2 RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rives ...
- RSA加密解密及数字签名Java实现
http://my.oschina.net/jiangli0502/blog/171263
- RSA 加密 解密 (长字符串) JAVA JS版本加解密
系统与系统的数据交互中,有些敏感数据是不能直接明文传输的,所以在发送数据之前要进行加密,在接收到数据时进行解密处理:然而由于系统与系统之间的开发语言不同. 本次需求是生成二维码是通过java生成,由p ...
- RSA加密解密实现(JAVA)
1.关于RSA算法的原理解析参考:http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html 2.RSA密钥长度.明文长度和密 ...
- C# Java间进行RSA加密解密交互(二)
原文:C# Java间进行RSA加密解密交互(二) 接着前面一篇文章C# Java间进行RSA加密解密交互,继续探讨这个问题. 在前面,虽然已经实现了C# Java间进行RSA加密解密交互,但是还是与 ...
- C# Java间进行RSA加密解密交互(三)
原文:C# Java间进行RSA加密解密交互(三) 接着前面一篇C# Java间进行RSA加密解密交互(二)说吧,在上篇中为了实现 /** * RSA加密 * @param text--待加密的明文 ...
- C#-java RSA加密解密
using Org.BouncyCastle.Math; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Securi ...
- java rsa加密解密
- 【转】 java RSA加密解密实现
[转] java RSA加密解密实现 该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar 下载地址:http://download.csdn.net/detai ...
随机推荐
- 【Android】Android Camera原始帧格式转换 —— 获取Camera图像(一)
概述: 做过Android Camera图像采集和处理的朋友们应该都知道,Android手机相机采集的原始帧(RawFrame)默认是横屏格式的,而官方API有没有提供一个设置Camera采集图像的 ...
- Python+Selenium进行UI自动化测试项目中,常用的小技巧4:日志打印,longging模块(控制台和文件同时输出)
在前段时间,为了给项目中加入日志功能,就想到了 logging 模块,百度logging一大推,都是各种复制的,并没有找到自己想要的结果:我的目的很简单,就是:在把日志写入文件的同时在控制台输出,更加 ...
- Eclipse Ctrl+Tab Alt+/ 快捷键
原来Eclipse的Next Editor 快捷键是 Ctrl+Tab 但是后几个版本将这个快捷键改为Ctrl+F6 了 在Keys设置下面 搜索 NextEditor 将其设置回来即可 同样 原来C ...
- [HttpClient]传递参数
package com.jerry.httpclient; import java.io.UnsupportedEncodingException; import java.util.ArrayLis ...
- URL具体解释
浏览器因特网资源:URL是浏览器寻找信息时所需的资源位置.通过URL.应用程序才干找到并使用共享因特网上大量的数据资源. 大部分URL都遵循一种标准的格式: ①HTTP协议(http://或者http ...
- XSS分析及预防(转)
阅读目录 XSS的种类和特点 XSS预防 总结 XSS(Cross Site Scripting),又称跨站脚本,XSS的重点不在于跨站点,而是在于脚本的执行.在WEB前端应用日益发展的今天,XSS漏 ...
- SharePoint 2013 图文开发系列之列表定义高级篇
转载自 http://www.cnblogs.com/jianyus/p/3484714.html SharePoint列表库,是我们使用过程中最常用的库,下面,我们简单介绍下代码定义自定义列表,主 ...
- 第六章:Python基础の反射与常用模块解密
本课主题 反射 Mapping 介绍和操作实战 模块介绍和操作实战 random 模块 time 和 datetime 模块 logging 模块 sys 模块 os 模块 hashlib 模块 re ...
- 【Java学习笔记之一】java关键字及作用
Java关键字及其作用 一. 总览: 访问控制 private protected public 类,方法和变量修饰符 abstract class extends final implements ...
- JQuery操作cookies
jQuery.cookie = function(name, value, options) { if (typeof value != 'undefined') { // name and valu ...