在构建Java代码实现前,我们要先完成keystore文件的构建。
1. 生成keystore文件
在命令行下执行以下命令:
Keytool –genkey -alias my_alias -keyalg RSA –keystore C:\mykeystore.keystore -validity 1830 -keysize 1024 -storepass 123456 -keypass pass -dname "CN=Jack,OU=腾讯,O=腾讯,L=深圳市,ST=广东省,C=Tecent"
命令说明:
(1) -genkey 表示要创建新的密钥
(2) -alias 别名,每个keystore都关联这一个独一无二的alias,这个alias通常不区分大小写。
(3) -keystore keystore文件的存储位置,文件扩展名为".keystore"。
(4) -keyalg 指定密钥的算法 (如 RSA DSA(如果不指定默认采用DSA))。
(5) -validity 指定有效期(天),默认90天。
(6) -keysize 指定密钥长度。
(7) -storepass 指定密钥库的访问密码(获取keystore信息所需的密码)
(8) -keypass 指定别名条目的密码(私钥的密码)
(9) -dname 指定证书拥有者信息 例如: "CN=名字与姓氏,OU=组织单位名称,O=组织名称,L=城市或区域名称,ST=州或省份名称,C=单位的两字母国家代码"。
OK,准备工作完成,开始Java实现!
2. 实现Java从keystore文件中提取公、私钥
由于无法通过KEYTOOL工具来提取私钥的..我们只能通过Java的KeyStore类getEntry() 或者getKey()来提取私钥,偶用的是getKey()方法的^_^…….
下面开始上代码:
由于从keystore文件中获取的公私钥均是字节码,不便于显示、传输,因此先上一个基础Coder类,实现Base64转码功能.
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* 基础加密组件
*
* @author 奔跑的蜗牛
* @version 1.0
* @since 1.0
*/
public abstract class Coder {
/**
* BASE64解密
*
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptBASE64(String key) throws Exception {
return (new BASE64Decoder()).decodeBuffer(key);
}
/**
* BASE64加密
*
* @param key
* @return
* @throws Exception
*/
public static String encryptBASE64(byte[] key) throws Exception {
return (new BASE64Encoder()).encodeBuffer(key).replace("\r", "").replace("\n", "");
}
}
下面的KeyStoreCoder类实获取公、私钥,以及实现RSA加密算法的公钥加密、私钥解密功能:
import java.io.FileInputStream;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import com.techshino.base.Coder;
public class KeyStoreCoder extends Coder {
/**
* Java密钥库(Java Key Store,JKS)KEY_STORE
*/
public static final String KEY_STORE = "JKS";
public static final String X509 = "X.509";
/**
* 获得KeyStore
*
* @author 奔跑的蜗牛
* @version 2012-3-16
* @param keyStorePath
* @param password
* @return
* @throws Exception
*/
private static KeyStore getKeyStore(String keyStorePath, String password)
throws Exception {
FileInputStream is = new FileInputStream(keyStorePath);
KeyStore ks = KeyStore.getInstance(KEY_STORE);
ks.load(is, password.toCharArray());
is.close();
return ks;
}
/**
* 由KeyStore获得私钥
* @author 奔跑的蜗牛
* @param keyStorePath
* @param alias
* @param storePass
* @return
* @throws Exception
*/
private static PrivateKey getPrivateKey(String keyStorePath, String alias, String storePass, String keyPass) throws Exception {
KeyStore ks = getKeyStore(keyStorePath, storePass);
PrivateKey key = (PrivateKey) ks.getKey(alias, keyPass.toCharArray());
return key;
}
/**
* 由Certificate获得公钥
* @author 奔跑的蜗牛
* @param keyStorePath
* KeyStore路径
* @param alias
* 别名
* @param storePass
* KeyStore访问密码
* @return
* @throws Exception
*/
private static PublicKey getPublicKey(String keyStorePath, String alias, String storePass) throws Exception {
KeyStore ks = getKeyStore(keyStorePath, storePass);
PublicKey key = ks.getCertificate(alias).getPublicKey();
return key;
}
/**
* 从KeyStore中获取公钥,并经BASE64编码
* @author 奔跑的蜗牛
* @param keyStorePath
* @param alias
* @param storePass
* @return
* @throws Exception
*/
public static String getStrPublicKey(String keyStorePath, String alias,String storePass) throws Exception{
PublicKey key = getPublicKey(keyStorePath, alias, storePass);
String strKey = Coder.encryptBASE64(key.getEncoded());
return strKey;
}
/**
* 获取经BASE64编码后的私钥
* @author 奔跑的蜗牛
* @param keyStorePath
* @param alias
* @param storePass
* @param keyPass
* @return
* @throws Exception
*/
public static String getStrPrivateKey(String keyStorePath, String alias,String storePass, String keyPass) throws Exception{
PrivateKey key = getPrivateKey(keyStorePath, alias, storePass, keyPass);
String strKey = Coder.encryptBASE64(key.getEncoded());
return strKey;
}
/**
* 使用公钥加密数据
* @author 奔跑的蜗牛
* @param publicKey
* @param srcData
* @return
* @throws Exception
*/
public static String encryptByPublicKey(String publicKey, String srcData) throws Exception{
//解密
byte[] pk = Coder.decryptBASE64(publicKey);
X509EncodedKeySpec spec = new X509EncodedKeySpec(pk);
KeyFactory kf = KeyFactory.getInstance("RSA");
//获取公钥
PublicKey pubKey = kf.generatePublic(spec);
// 对数据加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] doFinal = cipher.doFinal(srcData.getBytes());
return encryptBASE64(doFinal);
}
/**
* 使用私钥解密数据
* @author 奔跑的蜗牛
* @param privateKey
* @param data
* @return
* @throws Exception
*/
public static String descryptByPrivateKey(String privateKey, String data) throws Exception{
// BASE64转码解密私钥
byte[] pk = Coder.decryptBASE64(privateKey);
// BASE64转码解密密文
byte[] text = decryptBASE64(data);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(pk);
KeyFactory kf = KeyFactory.getInstance("RSA");
// 获取私钥
PrivateKey prvKey = kf.generatePrivate(spec);
// 对数据加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, prvKey);
byte[] doFinal = cipher.doFinal(text);
return new String(doFinal);
}
}
再给出一个测试类,看看加解密效果:
package com.techshino;
import com.techshino.keystore.KeyStoreCoder;
public class TestDemo {
public static void main(String[] args) {
// 公钥
String strPublicKey = "";
// 私钥
String strPrivateKey = "";
try {
strPublicKey = KeyStoreCoder.getStrPublicKey("F:\\GF.keystore", "myalias", "123456");
System.out.println("公钥 = 【" + strPublicKey + "】");
strPrivateKey = KeyStoreCoder.getStrPrivateKey("F:\\GF.keystore", "myalias", "123456", "pass");
System.out.println("\n私钥 = 【" + strPrivateKey + "】");
} catch (Exception e1) {
e1.printStackTrace();
}
// 原文
String originalText = "Java实现RSA加密算法!";
try {
// RSA算法 公钥加密随机数
String secretText = KeyStoreCoder.encryptByPublicKey(strPublicKey, originalText);
System.out.println("\n经RSA公钥加密后 = " + secretText);
System.out.println("\n经RSA公钥加密后长度 = " + secretText.length());
String text = KeyStoreCoder.descryptByPrivateKey(strPrivateKey, secretText);
System.out.println("\n经RSA私钥解密后 = 【" + text + "】");
System.out.println("\n经RSA私钥解密后长度 = 【" + text.length() + "】");
} catch (Exception e) {
e.printStackTrace();
}
}
}
控制台输出:
公钥 = 【MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5hLd9FryBcXdlKKGICd3/axQ85V5QmB/0P7a5KhZr0vJaGX+7YRJt4NYpH1+pEob0TkFaFXzYZSZIZa3R63tS1pWpvKSWdSEy1Spb9qBS1FMp0j8vhQN1ydFv1Fh3Ds6vqBoGYyvqmkRLworLDUiRWuEQqxNcsNjx2HMJnhpdxwIDAQAB】
私钥 = 【MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALmEt30WvIFxd2UooYgJ3f9rFDzlXlCYH/Q/trkqFmvS8loZf7thEm3g1ikfX6kShvROQVoVfNhlJkhlrdHre1LWlam8pJZ1ITLVKlv2oFLUUynSPy+FA3XJ0W/UWHcOzq+oGgZjK+qaREvCissNSJFa4RCrE1yw2PHYcwmeGl3HAgMBAAECgYEAgcFvzQ/v/OFtztUiVdIA8brlRspusxQTlXRSyyPC1tuOIrKfAmIcz7loUQ7ei5Sny4xIbUeGMJxesFhdwOthLxdcM54/lLW5ZCukUdUeLhjec1zTwCYZ9P1Ihrt63HOFRIVymak3f+eIWi4vmlNghSxyUGmXz1TYj/hI8wzWeZECQQDt7O5o+tZDGNPTzb4ppSyeZcRClcaLnvenig7Jyi3EOfv/gydANcUex5Fr8AnCkzAPIF0R3jU1vBbc0KKfnX1dAkEAx5yYjYQMJIFrJB6PYjhlwsOQi+cKFnphHnvaxPWP+LVAEduxjcKonvMmwqDq+6163omeXYEDn02pqeZoWMlxcwJAIpy7Oi5ziSNNfZyKs4hB63EmkgEz9w/TO15MNHLjIY7F6C/uP9sSqB2kPC2ZXeMHtMuifnzzBLQuJ0V6wvmoSQJBAKtfzLGi7vHgkuXdvuhq1yMR1+XlJAoMY5lSaI607ThwFGPApH265B4jT+HFWjldxaGNsYNBoqSAfuu5P1kLCfUCQQCJOv9FKXh5uWNO+Rcg4l7xwpnfCWtZKqrEWDy0cCfllfUPs0t8uRNZPKuroVGrZKJuvSGvQwM5g2pTAwRuctpM】
经RSA公钥加密后 = Ktj2HnI9MddXTcpYvORDrad9VmpMshBxMNro3QVXDw4meWadQXnEhc4s7w5sqPQezVCXEvDaONjngftXaYU5pagibaHh6jloIz562nqIDdYm91mbY1N8rgLH6S04zm4oqBhNai6xL5G/ecHvIySfCOqyItS1qWf7Umywhogluwc=
经RSA公钥加密后长度 = 172
经RSA私钥解密后 = 【Java实现RSA加密算法!】
经RSA私钥解密后长度 = 【14】
由此完成了Java实现RSA加解密功能(公钥加密、私钥解密),欢迎大家提出各种建议,大家互相学习~~~O(∩_∩)O~~~