RSA公钥加密算法,一种非对称加密方式,是服务器与客户端之间通讯中最常用的加密方式。非对称加密密钥有两个,分别为公开密钥(publickey)和私有密钥(privatekey),公开密钥与私有密钥是一对。如果用公开密钥对数据加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有对应的公开密钥才能解密。
一般情况下都是采用公钥加密数据,因为公钥是向外公开大家都可以知道,但密文只有私钥能够解开。使用私钥加密适合用于签名,使用公钥解密验证私钥身份。
代码;
package com.test;
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.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
public class RSA {
private static final String ALGORITHM = "RSA";
/**
* 公钥加密
*
* @param src
* 明文
* @param key
* 密钥
* @return
*/
public static String RSAPublicEncrypt(String src, String key) {
try {
PublicKey pubkey = getPublicKeyFromX509(ALGORITHM, key);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubkey);
byte bytes[] = src.getBytes("UTF-8");
byte[] encrypted = blockCipher(cipher, bytes, Cipher.ENCRYPT_MODE);
return bytes2Hex(encrypted);
} catch (Exception e) {
return null;
}
}
/**
* 私钥解密
*
* @param src
* 密文
* @param key
* 密钥
* @return
*/
public static String RSAPrivateDncrypt(String src, String key) {
try {
PrivateKey prikey = getEncodedKeySpecPKCS8(ALGORITHM, key);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, prikey);
byte bytes[] = toByte(src);
byte[] decrypted = blockCipher(cipher, bytes, Cipher.DECRYPT_MODE);
return new String(decrypted, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 私钥加密
*
* @param src
* 明文
* @param key
* 密钥
* @return
*/
public static String RSAPrivateEncrypt(String src, String key) {
try {
PrivateKey prikey = getEncodedKeySpecPKCS8(ALGORITHM, key);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, prikey);
byte bytes[] = src.getBytes("UTF-8");
byte[] encrypted = blockCipher(cipher, bytes, Cipher.ENCRYPT_MODE);
return bytes2Hex(encrypted);
} catch (Exception e) {
return null;
}
}
/**
* 公钥解密
*
* @param src
* 密文
* @param key
* 密钥
* @return
*/
public static String RSAPublicDncrypt(String src, String key) {
try {
PublicKey pubkey = getPublicKeyFromX509(ALGORITHM, key);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, pubkey);
byte bytes[] = toByte(src);
byte[] decrypted = blockCipher(cipher, bytes, Cipher.DECRYPT_MODE);
return new String(decrypted, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 得到公钥
*/
private static PublicKey getPublicKeyFromX509(String algorithm,
String bysKey) throws NoSuchAlgorithmException, Exception {
byte[] decodedKey = toByte(bysKey);
X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodedKey);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
return keyFactory.generatePublic(x509);
}
/**
* 得到私钥
*/
private static PrivateKey getEncodedKeySpecPKCS8(String algorithm,
String bysKey) throws NoSuchAlgorithmException, Exception {
byte[] decodedKey = toByte(bysKey);
PKCS8EncodedKeySpec PKCS8 = new PKCS8EncodedKeySpec(decodedKey);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
return keyFactory.generatePrivate(PKCS8);
}
private static byte[] blockCipher(Cipher cipher, byte[] bytes, int mode)
throws IllegalBlockSizeException, BadPaddingException {
byte[] scrambled = new byte[0];
byte[] toReturn = new byte[0];
// 如果我们使用长100字节块加密。解密需要128长度
int length = (mode == Cipher.ENCRYPT_MODE) ? 100 : 128;
byte[] buffer = null;
if (bytes.length <= length) {
return cipher.doFinal(bytes);
} else {
buffer = new byte[length];
}
for (int i = 0; i < bytes.length; i++) {
if ((i > 0) && (i % length == 0)) {
scrambled = cipher.doFinal(buffer);
toReturn = append(toReturn, scrambled);
int newlength = length;
if (i + length > bytes.length) {
newlength = bytes.length - i;
}
buffer = new byte[newlength];
}
buffer[i % length] = bytes[i];
}
scrambled = cipher.doFinal(buffer);
toReturn = append(toReturn, scrambled);
return toReturn;
}
private static byte[] append(byte[] prefix, byte[] suffix) {
byte[] toReturn = new byte[prefix.length + suffix.length];
for (int i = 0; i < prefix.length; i++) {
toReturn[i] = prefix[i];
}
for (int i = 0; i < suffix.length; i++) {
toReturn[i + prefix.length] = suffix[i];
}
return toReturn;
}
/**
* 随机生成密钥对
*/
public static Map<String, String> genKeyPair() {
KeyPairGenerator keyPairGen = null;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 第一个参数为秘钥长度,当需要2048加密只需修改秘钥长度即可
keyPairGen.initialize(1024, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
Map<String, String> key = new HashMap<String, String>();
key.put("PrivateKey", bytes2Hex((keyPair.getPrivate().getEncoded())));
key.put("PublicKey", bytes2Hex(keyPair.getPublic().getEncoded()));
return key;
}
/**
* Byte[]转16进制
*
* @param bts
* @return
*/
private static String bytes2Hex(byte[] bts) {
String des = "";
String tmp = null;
for (int i = 0; i < bts.length; i++) {
tmp = (Integer.toHexString(bts[i] & 0xFF));
if (tmp.length() == 1) {
des += "0";
}
des += tmp;
}
return des;
}
/**
* 将16进制转换为byte数组
*
* @param hexString
* 16进制字符串
* @return byte数组
*/
public static byte[] toByte(String hexString) {
int len = hexString.length() / 2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
16).byteValue();
return result;
}
}
测试代码:
static Map<String, String> keyMap;
public static void main(String[] args) {
keyMap = RSA.genKeyPair();
String privateKey = keyMap.get("PrivateKey");
String publicKey = keyMap.get("PublicKey");
System.out.println("公钥===" + publicKey);
System.out.println("私钥===" + privateKey);
String str = RSA.RSAPublicEncrypt("123456", publicKey);
System.out.println("公钥加密后的数据:" + str);
str = RSA.RSAPrivateDncrypt(str, privateKey);
System.out.println("私钥解密后的数据:" + str);
str = RSA.RSAPrivateEncrypt(str, privateKey);
System.out.println("私钥加密后的数据:" + str);
str = RSA.RSAPublicDncrypt(str, publicKey);
System.out.println("公钥解密后的数据:" + str);
}