RSA加密解密实现详情
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* RSA加密解密实现详情
* **/
public class RSA001Utils {
public static final String RSA = "RSA";
private static final String PUBLIC_KEY = "RSAPublicKey";
private static final String PRIVATE_KEY = "RSAPrivateKey";
//-------------------------------------01-----------------------------------//
/*公钥和私钥可以通过KeyPairGenerator执行generateKeyPair()后生成密钥对KeyPair,
通过KeyPair.getPublic()和KeyPair.getPrivate()来获取。
如下代码:*/
/**
* 获取 密钥对KeyPair
* RSA的公钥和私钥是由KeyPairGenerator生成的,获取KeyPairGenerator的实例后还需要设置其密钥位数。
* 设置密钥位数越高,加密过程越安全,一般使用1024位。如下代码:
* **/
public static KeyPair getKeyPair(){
KeyPair keyPair=null;
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);
// 密钥位数//设置密钥位数越高,加密过程越安全,一般使用1024位
keyPairGen.initialize(1024);
/*//自定义securerandom 实现作为随机源
SecureRandom secrand = new SecureRandom();
secrand.setSeed("syj".getBytes()); // 初始化随机产生器
keyPairGen.initialize(1024, secrand);*/
// 动态生成密钥对,这是当前最耗时的操作,一般要2s以上。
keyPair = keyPairGen.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return keyPair;
}
/**
* 获取 公钥和私钥
* 公钥和私钥可以通过KeyPairGenerator执行generateKeyPair()后生成密钥对KeyPair,
* 通过KeyPair.getPublic()和KeyPair.getPrivate()来获取。如下代码:
* **/
public static Map
Map
if(keyPair!=null){
// 公钥
PublicKey publicKey = keyPair.getPublic();//密钥对KeyPair获取公钥
keyMap.put(PUBLIC_KEY, publicKey);
byte[] publicKeyData = publicKey.getEncoded();
PublicKey publicKey2=getPublicKey(publicKeyData);//由byte[]还原PublicKey
try {
String public_key=encryptBASE64(publicKeyData);//由byte[]转字符串public_key
System.out.println("public_key:");
System.out.println(public_key);
byte[] privateKeyData2=decryptBASE64(public_key);//由字符串转byte[]
int a=0;
} catch (Exception e) {
e.printStackTrace();
}
// 私钥
PrivateKey privateKey = keyPair.getPrivate();//密钥对KeyPair获取私钥
keyMap.put(PRIVATE_KEY, privateKey);
byte[] privateKeyData = privateKey.getEncoded();
PrivateKey privateKey2=getPrivateKey(privateKeyData);//由byte[]还原PrivateKey
try {
String private_key=encryptBASE64(privateKeyData);//由byte[]转字符串private_key
System.out.println("private_key:");
System.out.println(private_key);
byte[] privateKeyData2=decryptBASE64(private_key);//由字符串转byte[]
int a=0;
} catch (Exception e) {
e.printStackTrace();
}
}
return keyMap;
}
//------------------------------------02------------------------------------//
/*公钥和私钥都有它们自己独特的比特编码,可以通过getEncoded()方法获取,返回类型为byte[]。
通过byte[]可以再度将公钥或私钥还原出来。
具体代码如下:*/
/**
* 通过公钥byte[]将公钥还原,适用于RSA算法
* **/
public static PublicKey getPublicKey(byte[] keyBytes) {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
PublicKey publicKey=null;
try {
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
publicKey = keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return publicKey;
}
/**
* 通过私钥byte[]将公钥还原,适用于RSA算法
* **/
public static PrivateKey getPrivateKey(byte[] keyBytes) {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey privateKey=null;
try {
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
privateKey = keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return privateKey;
}
///
/* 公钥和私钥都有它们自己独特的比特编码,可以通过getEncoded()方法获取,返回类型为byte[]。
由 BASE64Encoder.encodeBuffer(key)把类型为byte[]转字符串String
*/
public static String encryptBASE64(byte[] key) throws Exception {
return (new BASE64Encoder()).encodeBuffer(key);
}
/*
公钥和私钥都有它们自己独特的比特编码,可以通过getEncoded()方法获取,返回类型为byte[]。
由 BASE64Encoder.encodeBuffer(key)把byte[]转字符串String;
再由BASE64Encoder.decodeBuffer(key)把字符串String转byte[]
*/
public static byte[] decryptBASE64(String key) throws Exception {
return (new BASE64Decoder()).decodeBuffer(key);
}
///
//-----------------------------------------03-------------------------------//
/*在上文讲到的RSA算法实现过程中提到(N,e)是公钥,(N,d)是私钥。既然已经获取到了PublicKey和PrivateKey了,
那如何取到N、e、d这三个值呢。要取到这三个值,首先要将PublicKey和PrivateKey强制转换成RSAPublicKey和RSAPrivateKey。
共同的N值可以通过getModulus()获取。
执行RSAPublicKey.getPublicExponent()可以获取到公钥中的e值,
执行RSAPrivateKey.getPrivateExponent()可以获取私钥中的d值。
这三者返回类型都是BigInteger。
代码如下:*/
/**
* 打印公钥信息
* N、e值
* **/
public static void printPublicKeyInfo(PublicKey publicKey){
if(publicKey!=null){
RSAPublicKey rsaPublicKey = (RSAPublicKey)publicKey;
System.out.println("RSAPublicKey:");
System.out.println("(N值)Modulus="+rsaPublicKey.getModulus().toString());
System.out.println("(e值)PublicExponent="+rsaPublicKey.getPublicExponent().toString());
}else{
System.out.println("printPublicKeyInfo-------失败");
}
}
/**
* 打印私钥信息
* N、d值
* **/
public static void printPrivateKeyInfo(PrivateKey privateKey){
if(privateKey!=null){
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey ) privateKey;
System.out.println("RSAPrivateKey:");
System.out.println("(N值)Modulus="+rsaPrivateKey.getModulus().toString());
System.out.println("(d值)PrivateExponent="+rsaPrivateKey.getPrivateExponent().toString());
}else{
System.out.println("printPrivateKeyInfo-------失败");
}
}
//-----------------------------------------04-------------------------------//
/*由于程序中动态生成KeyPair对明文加密后生成的密文是不可测的,
所以在实际开发中通常在生成一个KeyPair后将公钥和私钥的N、e、d这三个特征值记录下来,
在真实的开发中使用这三个特征值再去将PublicKey和PrivateKey还原出来。
还原方法如下:*/
/**
* 使用N、e值还原公钥
* **/
public static PublicKey getPublicKey(String modulus, String publicExponent) {
BigInteger bigIntModulus = new BigInteger(modulus);
BigInteger bigIntPrivateExponent = new BigInteger(publicExponent);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus,bigIntPrivateExponent);
PublicKey publicKey=null;
try {
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
publicKey = keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
}catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return publicKey;
}
/**
* 使用N、d值还原私钥
* **/
public static PrivateKey getPrivateKey(String modulus, String privateExponent) {
BigInteger bigIntModulus = new BigInteger(modulus);
BigInteger bigIntPrivateExponent = new BigInteger(privateExponent);
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(bigIntModulus,bigIntPrivateExponent);
PrivateKey privateKey=null;
try {
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
privateKey = keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
}catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return privateKey;
}
public static void main(String[] args) {
try {
KeyPair keyPair = RSA001Utils.getKeyPair();//获取 密钥对KeyPair
Map
RSA001Utils.printPublicKeyInfo((PublicKey)keyMap.get(PUBLIC_KEY));
System.out.println("----------------------------------");
RSA001Utils.printPrivateKeyInfo((PrivateKey)keyMap.get(PRIVATE_KEY));
} catch (Exception e) {
e.printStackTrace();
}
}
}