记录下RSA 工具类,提供加密,解密,签名,生成密钥对等方法,以便以后使用。
import java.io.File;
import java.io.IOException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Random;
import javax.crypto.Cipher;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.io.FileUtils;
/**
*
* RSA 工具类。提供加密,解密,签名,生成密钥对等方法。
*
*/
public final class RSA {
public static final String RSA_CRYPT_ALGORITHM_NAME = "RSA";
public static final String RSA_SIGN_ALGORITHM_NAME = "MD5withRSA";
private static final int RSA_KEY_LENGTH = 1024;
/**
*
* 生成密钥对
*
* @return KeyPair
*/
private static KeyPair generateKeyPair() throws Exception {
try {
KeyPairGenerator keyPairGen = KeyPairGenerator
.getInstance(RSA_CRYPT_ALGORITHM_NAME);
final int KEY_SIZE = RSA_KEY_LENGTH;// 块加密的大小,值太大会影响效率
SecureRandom secrand = new SecureRandom();
//这里的种子一定要随机,不然会产生相同的key,就没有安全性可言了。。。
secrand.setSeed(RandomUtils.generateString(RSA_KEY_LENGTH).getBytes()); // 初始化随机产生器
keyPairGen.initialize(KEY_SIZE, secrand);
KeyPair keyPair = keyPairGen.genKeyPair();
return keyPair;
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
/**
* 生产RSA密钥对,并且保存到文件中
*
* @param path
*/
public static void keyRSA(String path, boolean isBase64Encode)
throws Exception {
KeyPair kp = generateKeyPair();
// 获取公钥
PublicKey pubkey = kp.getPublic();
// 获取私钥
PrivateKey prikey = kp.getPrivate();
byte[] pubKeyBytes = pubkey.getEncoded();
byte[] priKeyBytes = prikey.getEncoded();
if (isBase64Encode) {
pubKeyBytes = Base64.encode(pubkey.getEncoded()).getBytes();
priKeyBytes = Base64.encode(prikey.getEncoded()).getBytes();
}
// 保存公钥到文件
if (StringUtils.isBlank(path)) {
path = "c:/";
} else {
if (!path.endsWith("/")) {
path = path + "/";
}
}
bytes2File(pubKeyBytes, path + "rsa.publicKey");
bytes2File(priKeyBytes, path + "rsa.privateKey");
}
private static void bytes2File(byte[] keyBytes,
String filePath) throws IOException {
File file = new File(filePath);
if (!file.getParentFile().exists())
file.getParentFile().mkdirs();
FileUtils.writeByteArrayToFile(file, keyBytes);
}
public static PublicKey generateRSAPublicKey(String path,
boolean base64Encoded) throws Exception {
return generateRSAPublicKey(getBytes(path), base64Encoded);
}
/**
* 生成公钥
*
* @param pubKeyString
* @return
* @throws Exception
*/
public static PublicKey generateRSAPublicKey(byte[] pubKeyByte,
boolean base64Encoded) throws Exception {
byte[] encodedKey = pubKeyByte;
// 先base64解码
if (base64Encoded) {
encodedKey = Base64.decode(new String(pubKeyByte));
}
X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(encodedKey);
KeyFactory keyFactory = KeyFactory
.getInstance(RSA_CRYPT_ALGORITHM_NAME);
return keyFactory.generatePublic(bobPubKeySpec);
}
public static PrivateKey generateRSAPrivateKey(String path,
boolean base64Encoded) throws Exception {
return generateRSAPrivateKey(getBytes(path), base64Encoded);
}
/**
* 生产私钥
*
* @param priKeyByte
* @return
* @throws Exception
*/
public static PrivateKey generateRSAPrivateKey(byte[] priKeyByte,
boolean base64Encoded) throws Exception {
byte[] encodedKey = priKeyByte;
// 先base64解码
if (base64Encoded) {
encodedKey = Base64.decode(new String(priKeyByte));
}
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(encodedKey);
KeyFactory keyFactory = KeyFactory
.getInstance(RSA_CRYPT_ALGORITHM_NAME);
return keyFactory.generatePrivate(priPKCS8);
}
private static byte[] getBytes(String path) throws IOException {
File file = new File(path);
return FileUtils.readFileToByteArray(file);
}
/**
* 加密
*
* @param key
* 加密的密钥
* @param data
* 待加密的明文数据
* @return 加密后的数据
*/
public static byte[] encrypt(Key key, byte[] data) throws Exception {
if (key != null) {
try {
Cipher cipher = Cipher.getInstance(RSA_CRYPT_ALGORITHM_NAME);
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 解密
*
* @param key
* 解密的密钥
* @param raw已经加密的数据
* @return 解密后的明文
*/
public static byte[] decrypt(Key key, byte[] raw) throws Exception {
if (key != null) {
try {
Cipher cipher = Cipher.getInstance(RSA_CRYPT_ALGORITHM_NAME);
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(raw);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 签名
*
* @param privateKey
* @param data
* @return
*/
public static byte[] sign(PrivateKey privateKey, byte[] data)
throws Exception {
try {
// 用私钥对信息生成数字签名
Signature signet = Signature.getInstance(RSA_SIGN_ALGORITHM_NAME);
signet.initSign(privateKey);
signet.update(data);
byte[] signed = signet.sign(); // 对信息的数字签名
return signed;
} catch (Exception e) {
throw new Exception(e);
}
}
/**
* 验证签名是否正确
*
* @param publicKey
* @param signed
* @param orig
* @return
*/
public static boolean verify(PublicKey publicKey, byte[] signed, byte[] orig)
throws Exception {
try {
Signature signetcheck = Signature
.getInstance(RSA_SIGN_ALGORITHM_NAME);
signetcheck.initVerify(publicKey);
signetcheck.update(orig);
if (signetcheck.verify(signed)) {
return true;
} else {
return false;
}
} catch (Exception e) {
throw new Exception(e);
}
}
public static void main(String[] args) throws Exception {
RSA.keyRSA("D:/12", true);
PublicKey publicKey = RSA.generateRSAPublicKey("D:/12/rsa.publicKey", true);
PrivateKey privateKey = RSA.generateRSAPrivateKey("D:/12/rsa.privateKey", true);
String str = "rsa test : KKC --> kkc ~ 88";
byte[] strByte = str.getBytes();
System.out.println("原字符串:" + str);
byte[] encrypt = RSA.encrypt(privateKey, strByte);
byte[] decrypt = RSA.decrypt(publicKey, encrypt);
System.out.println("解密后字符串:" + new String(decrypt));
System.out.println("原字符串、解密后字符串是否相同:" + new String(decrypt).equals(str));
byte[] sign = RSA.sign(privateKey, strByte);
System.out.println("原字符串验证签名:" + RSA.verify(publicKey, sign, strByte));
System.out.println("随机字符串验证签名:" + RSA.verify(publicKey, sign, RandomUtils.generateString(20).getBytes()));
}
}
class RandomUtils {
public static final String allChar = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* 返回一个定长的随机字符串(只包含大小写字母、数字)
*
* @param length 随机字符串长度
* @return 随机字符串
*/
public static String generateString(int length) {
StringBuffer sb = new StringBuffer();
Random random = new Random();
for (int i = 0; i < length; i++) {
sb.append(allChar.charAt(random.nextInt(allChar.length())));
}
return sb.toString();
}
}