Java实现RSA加密
末尾贴上代码↓↓↓↓↓↓↓↓↓↓↓↓
1.原理
2.实现过程
3. 公式
4.举例
p=13, q=11 , (p,q互质)
N=p*q=143
L=(p-1)*(q-1)=120
E=7 (E与L互质)
E *D ≡ 1 (mod L) 就是E*D mod L 等于 1 mod L (对于模L的余数相同)
取D=103 E*D=7*103=721 721 mod 120=1
公钥 (143,7) 私钥(143,103)
加密: 需要加密数据m=7 ,密文 c=(7^7 mod 143)=6
解密: 需要解密数据c=103, 原文 m=(6^103 mod 143) =7
5.最后简单谈谈RSA的安全性
首先,我们来探讨为什么RSA密码难于破解?
在RSA密码应用中,公钥KU是被公开的,即e和n的数值可以被第三方窃听者得到。破解RSA密码的问题就是从已知的e和n的数值(n等于pq),想法求出d的数值,这样就可以得到私钥来破解密文。从上文中的公式:d ≡e-1 (mod((p-1)(q-1)))或de≡1
(mod((p-1)(q-1))) 我们可以看出。密码破解的实质问题是:从Pq的数值,去求出(p-1)和(q-1)。换句话说,只要求出p和q的值,我们就能求出d的值而得到私钥。
当p和q是一个大素数的时候,从它们的积pq去分解因子p和q,这是一个公认的数学难题。比如当pq大到1024位时,迄今为止还没有人能够利用任何计算工具去完成分解因子的任务。因此,RSA从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。
然而,虽然RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难度与大数分解难度等价。即RSA的重大缺陷是无法从理论上把握它的保密性能如何。
此外,RSA的缺点还有:A)产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。B)分组长度太大,为保证安全性,n 至少也要 600 bits 以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。因此,使用RSA只能加密少量数据,大量的数据加密还要靠对称密码算法。
6.Java代码
package com.my; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils; import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map; public class RSAUtils {
public static final String CHARSET = "UTF-8";
public static final String RSA_ALGORITHM = "RSA"; // ALGORITHM ['ælgərɪð(ə)m] 算法的意思 public static Map<String, String> createKeys(int keySize) {
// 为RSA算法创建一个KeyPairGenerator对象
KeyPairGenerator kpg;
try {
kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");
} // 初始化KeyPairGenerator对象,密钥长度
kpg.initialize(keySize);
// 生成密匙对
KeyPair keyPair = kpg.generateKeyPair();
// 得到公钥
Key publicKey = keyPair.getPublic();
String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());
// 得到私钥
Key privateKey = keyPair.getPrivate();
String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());
// map装载公钥和私钥
Map<String, String> keyPairMap = new HashMap<String, String>();
keyPairMap.put("publicKey", publicKeyStr);
keyPairMap.put("privateKey", privateKeyStr);
// 返回map
return keyPairMap;
} /**
* 得到公钥
* @param publicKey 密钥字符串(经过base64编码)
* @throws Exception
*/
public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
// 通过X509编码的Key指令获得公钥对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
return key;
} /**
* 得到私钥
* @param privateKey 密钥字符串(经过base64编码)
* @throws Exception
*/
public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
// 通过PKCS#8编码的Key指令获得私钥对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
return key;
} /**
* 公钥加密
* @param data
* @param publicKey
* @return
*/
public static String publicEncrypt(String data, RSAPublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
} catch (Exception e) {
throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
}
} /**
* 私钥解密
* @param data
* @param privateKey
* @return
*/ public static String privateDecrypt(String data, RSAPrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);
} catch (Exception e) {
throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
}
} /**
* 私钥加密
* @param data
* @param privateKey
* @return
*/ public static String privateEncrypt(String data, RSAPrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
//每个Cipher初始化方法使用一个模式参数opmod,并用此模式初始化Cipher对象。此外还有其他参数,包括密钥key、包含密钥的证书certificate、算法参数params和随机源random。
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength()));
} catch (Exception e) {
throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
}
} /**
* 公钥解密
* @param data
* @param publicKey
* @return
*/ public static String publicDecrypt(String data, RSAPublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);
} catch (Exception e) {
throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
}
} //rsa切割解码 , ENCRYPT_MODE,加密数据 ,DECRYPT_MODE,解密数据
private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
int maxBlock = 0; //最大块
if (opmode == Cipher.DECRYPT_MODE) {
maxBlock = keySize / 8;
} else {
maxBlock = keySize / 8 - 11;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] buff;
int i = 0;
try {
while (datas.length > offSet) {
if (datas.length - offSet > maxBlock) {
//可以调用以下的doFinal()方法完成加密或解密数据:
buff = cipher.doFinal(datas, offSet, maxBlock);
} else {
buff = cipher.doFinal(datas, offSet, datas.length - offSet);
}
out.write(buff, 0, buff.length);
i++;
offSet = i * maxBlock;
}
} catch (Exception e) {
throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常", e);
}
byte[] resultDatas = out.toByteArray();
IOUtils.closeQuietly(out);
return resultDatas;
} // 简单测试____________
public static void main(String[] args) throws Exception {
Map<String, String> keyMap = RSAUtils.createKeys(1024);
String publicKey = keyMap.get("publicKey");
String privateKey = keyMap.get("privateKey");
System.out.println("公钥: \n\r" + publicKey);
System.out.println("私钥: \n\r" + privateKey); System.out.println("公钥加密——私钥解密");
String str = "站在大明门前守卫的禁卫军,事先没有接到\n" + "有关的命令,但看到大批盛装的官员来临,也就\n" + "以为确系举行大典,因而未加询问。进大明门即\n" + "为皇城。文武百官看到端门午门之前气氛平静,\n" + "城楼上下也无朝会的迹象,既无几案,站队点名\n" + "的御史和御前侍卫“大汉将军”也不见踪影,不免\n"
+ "心中揣测,互相询问:所谓午朝是否讹传?";
System.out.println("\r明文:\r\n" + str);
System.out.println("\r明文大小:\r\n" + str.getBytes().length);
String encodedData = RSAUtils.publicEncrypt(str, RSAUtils.getPublicKey(publicKey)); //传入明文和公钥加密,得到密文
System.out.println("密文:\r\n" + encodedData);
String decodedData = RSAUtils.privateDecrypt(encodedData, RSAUtils.getPrivateKey(privateKey)); //传入密文和私钥,得到明文
System.out.println("解密后文字: \r\n" + decodedData); } }
Java实现RSA加密的更多相关文章
- JAVA实现RSA加密,非对称加密算法
RSA.java package org.icesnow.jeasywx.util.security; import java.security.Key; import java.security.K ...
- Java使用RSA加密解密及签名校验
该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar注意:RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行 ...
- C# 与JAVA 的RSA 加密解密交互,互通,C#使用BouncyCastle来实现私钥加密,公钥解密的方法
因为C#的RSA加密解密只有公钥加密,私钥解密,没有私钥加密,公钥解密.在网上查了很久也没有很好的实现.BouncyCastle的文档少之又少.很多人可能会说,C#也是可以的,通过Biginteger ...
- Java使用RSA加密解密签名及校验
RSA加密解密类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ...
- Java采用RSA加密及解密技术的有关Maven项目的配置流程:
第一步: 获得RSA公钥私钥(秘钥格式:PKCS#8 ,测试使用的是无私钥密码的) 公钥: -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4G ...
- php与JAVA的RSA加密互通
Java 版本RSA 进行加密解密 在网上查询了好几天,最终找到解决方案,网络上都是通过Cipher.getInstance("RSA"); 而改成Cipher.getInstan ...
- JAVA实现RSA加密解密 非对称算法
首先RSA是一个非对称的加密算法.所以在使用该算法加密解密之前,必须先行生成密钥对.包含公钥和私钥 JDK中提供了生成密钥对的类KeyPairGenerator,实比例如以下: public stat ...
- iOS and JAVA 的 RSA 加密解密 (转载整理 )
参考原文地址:http://www.cnblogs.com/makemelike/articles/3802518.html (至于RSA的基本原理,大家可以看 阮一峰的网络日志 的 RSA算法原理( ...
- 【转】php和java之间rsa加密互通
以下是php封装好的类,引入即可使用 <?php /** * 作者:pjp * 邮箱:vippjp@163.com */ class RSA{ private $privateKey='';// ...
- python vs java的rsa加密
首先:java的加密解密模块需要更加精细的算法细节指定 java的加密方式 javax.crypto.Cipher,定义的获取方式 tatic Cipher getInstance(String tr ...
随机推荐
- JavaScript笔记 – 程序语法设计
一.基础语法设计 JavaScript是可以与HTML标记语言混合.用于网页交互式的解释型脚本语言.由国际标准ECMAScript提供核心语言功能.文档对象模型(DOM)提供访问和操作网页内容的方法和 ...
- 6 Accessing and Managing Symbols with armlink
6.4 Image$$ execution region symbols The linker generates Image$$ symbols for every execution region ...
- linux最常用vim命令记录
先来一张图了解3种模式: 一.输入vim 命令,进入命令模式 此时可执行: 1.行号显示 (1):set nu 显示文本的行号: :nonu 取消显示行号 2.光标移动 (1)n<E ...
- StringUtils里的isEmpty和isBlank的区别
这边首先以一个简单的测试代码来解释这两者的区别: @Test void stringTest(){ String a = " "; boolean empty = StringUt ...
- python学习6—数据类型之集合与字符串格式化
python学习6—数据类型之集合与字符串格式化 1. 使用id()可以查看一个变量的内存地址: name = 'alex' id(name) 2. 进制转换 十进制转换为二进制等: a = 10 # ...
- USACO2012 Haybale stacking /// 区间表示法 oj21556
题目大意:N个方块 标号1~N K个操作 操作a b 表示标号a~b区间每位多加一个方块 Input * Line 1: Two space-separated integers, N K. * ...
- 解决maven项目创建过慢的问题以及快捷键
分别在创建项目时填入以下值: Name:archetypeCatalogValue:internal idea常用的快捷键 Alt+回车 导入包,自动修正 Ctrl+N 查找类 Ctrl+Shift+ ...
- ASP.NET打开项目错误:将指定的计数添加到该信号量中会导致其超过最大计数。
1.错误如图 2.解决方案 重启IIS即可,运行-> 输入IISRESET 命令 即可重启IIS,如图
- Yii2 在php 7.2环境下运行,提示 Cannot use ‘Object’ as class name
出错原因是: Object是php7.2中的保留类名,不可以使用Object作为类的名称. The object name was previously soft-reserved in PHP 7. ...
- 关于jquery ajax项目总结
$.ajax({ url:"../action/BorrowAction.php?action=oready", async:true,//异步请求 ...