密钥管理是对称加密算法系统不容忽视的问题,它成为安全系统中最为薄弱的环节。为了弥补这一弱势,非对称加密算法应运而生。
非对称加密算法源于DH算法(Diffie-Hellman,密钥交换算法),由W.Diffie和M.Hellman共同提出。该算法为非对称加密算法奠定了基础,堪称非对称加密算法之鼻祖。
DH算法提出后,国际上相继出现了各种实用性更强的非对称加密算法,其构成主要是基于数学问题的求解,主要分为两类:
-
基于因子分解难题。RSA算法是最为典型的非对称加密算法,该算法由美国麻省理工学院(MIT)的Ron Rivest、Adi Shamir和Leonard Adleman三位学者提出,并以这三位学者的姓氏开头字母命名,称为RSA算法。RSA算法是当今应用范围最为广泛的非对称加密算法,也是第一个既能用于数据加密也能用于数字签名的算法。
-
基于离散对数难题。ElGamal算法由TaherElGamal提出,以自己的名字命名。该算法既可用于加密/解密,也可用于数字签名,并为数字签名算法形成标准提供参考。美国的DSS(Digital Signature Standard,数据签名标准)的DSA(Digital Signature Algorithm,数字签名算法)经ElGamal算法演变而来。
ECC(Elliptical Curve Cryptography,椭圆曲线加密)算法以椭圆曲线理论为基础,在创建密钥时可做到更快、更小,并且更有效。ECC算法通过椭圆曲线方程式的性质产生密钥,而不是采用传统的方法利用大质数的积来产生。
1. 密钥交换算法(DH&ECDH)
1.1 DH
对称加密算法提高数据安全性的同时带来了密钥管理的复杂性。消息收发双方若想发送加密消息,必须事先约定好加密算法并发放密钥。而如何安全的传递密钥,成为对称加密算法的一个棘手问题。密钥交换算法(Diffie-Hellman算法,简称DH算法)成为解决这一问题的金钥匙!
代码实现
public static final String KEY_ALGORITHM = "DH";
public static final String SECRET_ALGORITHM = "AES";
public static final int KEY_SIZE = 512;
public static final String PUBLIC_KEY = "DHPublicKey";
public static final String PRIVATE_KEY = "DHPrivateKey";
/**
* 生成甲方密钥对(含公钥、私钥)
*
* @return map
* @throws Exception 异常
*/
public Map<String, Object> initKey() throws Exception {
// 初始化密钥对生成器
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
// 生成密钥对
final KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 获取公钥
final PublicKey publicKey = keyPair.getPublic();
// 获取私钥
final PrivateKey privateKey = keyPair.getPrivate();
// 构造返回map
Map<String, Object> keyMap = new HashMap<>();
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
* 根据甲方公钥生成乙方密钥对(含公钥、私钥)
*
* @param key 甲方公钥
* @return map
* @throws Exception 异常
*/
public Map<String, Object> initKey(byte[] key) throws Exception {
// 解析甲方公钥
final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
// 实例化密钥工厂
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 产生甲方公钥
final PublicKey aPublicKey = keyFactory.generatePublic(x509EncodedKeySpec);
// 由甲方公钥构建乙方密钥
final DHParameterSpec dhParameterSpec = ((DHPublicKey) aPublicKey).getParams();
// 初始化密钥对生成器
final KeyPairGenerator dh = KeyPairGenerator.getInstance(keyFactory.getAlgorithm());
dh.initialize(dhParameterSpec);
// 生成密钥对
final KeyPair keyPair = dh.generateKeyPair();
// 获取公钥
final PublicKey publicKey = keyPair.getPublic();
// 获取私钥
final PrivateKey privateKey = keyPair.getPrivate();
// 构造返回map
Map<String, Object> keyMap = new HashMap<>();
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
* 生成密钥
* @param publicKey 对方公钥
* @param privateKey 自己私钥
* @return 密钥
* @throws Exception 异常
*/
public byte[] getSecretKey(byte[] publicKey, byte[] privateKey) throws Exception {
// 初始化密钥工厂
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 初始化公钥
final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
final PublicKey pubKey = keyFactory.generatePublic(x509EncodedKeySpec);
// 初始化私钥
final PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
final PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
// 实例化
final KeyAgreement keyAgreement = KeyAgreement.getInstance(keyFactory.getAlgorithm());
keyAgreement.init(priKey);
keyAgreement.doPhase(pubKey, true);
// 生成本地密钥
final SecretKey secretKey = keyAgreement.generateSecret(SECRET_ALGORITHM);
return secretKey.getEncoded();
}
/**
* 取得公钥
*
* @param keyMap 密钥map
* @return 公钥
*/
public byte[] getPublicKey(Map<String, Object> keyMap) {
final Key key = (Key) keyMap.get(PUBLIC_KEY);
return key.getEncoded();
}
/**
* 取得私钥
*
* @param keyMap 密钥map
* @return 私钥
*/
public byte[] getPrivateKey(Map<String, Object> keyMap) {
final Key key = (Key) keyMap.get(PRIVATE_KEY);
return key.getEncoded();
}
/**
* 数据加密
*
* @param data 待加密数据
* @param key 密钥
* @return 加密后数据
*/
public byte[] encrypt(byte[] data, byte[] key) throws Exception {
// 生成本地密钥
final SecretKeySpec secretKeySpec = new SecretKeySpec(key, SECRET_ALGORITHM);
// 数据加密
final Cipher cipher = Cipher.getInstance(secretKeySpec.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return cipher.doFinal(data);
}
/**
* 数据解密
*
* @param data 待解密数据
* @param key 密钥
* @return 解密后数据
*/
public byte[] decrypt(byte[] data, byte[] key) throws Exception {
// 生成本地密钥
final SecretKeySpec secretKeySpec = new SecretKeySpec(key, SECRET_ALGORITHM);
// 数据加密
final Cipher cipher = Cipher.getInstance(secretKeySpec.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
return cipher.doFinal(data);
}
测试用例
@Test
public void testDH() throws Exception {
final Map<String, Object> aKeyMap = initKey();
final byte[] aPublicKey = getPublicKey(aKeyMap);
final byte[] aPrivateKey = getPrivateKey(aKeyMap);
System.out.println("甲方公钥:" + Base64.toBase64String(aPublicKey));
System.out.println("甲方私钥:" + Base64.toBase64String(aPrivateKey));
final Map<String, Object> bKeyMap = initKey(aPublicKey);
final byte[] bPublicKey = getPublicKey(bKeyMap);
final byte[] bPrivateKey = getPrivateKey(bKeyMap);
System.out.println("乙方公钥:" + Base64.toBase64String(bPublicKey));
System.out.println("乙方私钥:" + Base64.toBase64String(bPrivateKey));
final byte[] aSecretKey = getSecretKey(bPublicKey, aPrivateKey);
final byte[] bSecretKey = getSecretKey(aPublicKey, bPrivateKey);
System.out.println("甲方密钥:" + Base64.toBase64String(aSecretKey));
System.out.println("乙方密钥:" + Base64.toBase64String(bSecretKey));
final byte[] aEncrypt = encrypt("我是阿汤哥".getBytes(), aSecretKey);
final byte[] bDecrypt = decrypt(aEncrypt, bSecretKey);
System.out.println("甲方加密消息:" + Base64.toBase64String(aEncrypt));
System.out.println("乙方解密消息:" + Base64.toBase64String(bDecrypt));
final byte[] bEncrypt = encrypt("Hello, 阿汤哥".getBytes(), bSecretKey);
final byte[] aDecrypt = decrypt(bEncrypt, aSecretKey);
System.out.println("乙方加密消息:" + Base64.toBase64String(bEncrypt));
System.out.println("甲方解密消息:" + Base64.toBase64String(aDecrypt));
}
使用jdk8执行本用例时如果报错
java.security.NoSuchAlgorithmException: Unsupported secret key algorithm: AES
at com.sun.crypto.provider.DHKeyAgreement.engineGenerateSecret(DHKeyAgreement.java:387)
at javax.crypto.KeyAgreement.generateSecret(KeyAgreement.java:648)
at com.jd.eps.eis.product.core.config.DHTest.getSecretKey(DHTest.java:110)
at com.jd.eps.eis.product.core.config.DHTest.testDH(DHTest.java:183)
可以通过增加vm参数 -Djdk.crypto.KeyAgreement.legacyKDF=true
解决。
执行结果
甲方公钥:MIHgMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANEAAJBAMCeFF4M4gFXNabyak7DplZnTVPJCNpw9eOao4BWNrdu8ptUiTg4kwmP8bxjot873vQ7QDg4cPyTFJGZ/c3HApE=
甲方私钥:MIHSAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQzAjEA1f2vYbDfzWpVlX8ib4ftWD5q24Mzh74C0L+ze8ienkfwv41dErOl0HqZOmmf18HN
乙方公钥:MIHgMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANEAAJBAJ3BzkiX8n6RurBasjqLYwCbewwX0ZkWykCzyQj6y/4uBgNX0m+0bgPX1emxlFt/N3ueC8803OhNcprcHRxschY=
乙方私钥:MIHSAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQzAjEAqi55vmMEF5pfS4//fvfqELLlo817cCRlRMOZ+sQ9HLtroIJ16x7RWusDpK75dqxA
甲方密钥:sSVOKIBcVtQ5h806csVXzmkPZWUhC75Xp9glwAjFWhY=
乙方密钥:sSVOKIBcVtQ5h806csVXzmkPZWUhC75Xp9glwAjFWhY=
甲方加密消息:DPftIVbpAGj7dkF73QB4zw==
乙方解密消息:我是阿汤哥
乙方加密消息:FTZnyPN+ZAzdqU4vEKjkMCo6U0TLlKPDyL3zoBSGvvQ=
甲方解密消息:Hello, 阿汤哥
1.2 ECDH
JDK8没有ECDH的实现,需要添加Provider。
Security.addProvider(new BouncyCastleProvider());
根据甲方公钥生成乙方密钥对时需对ParameterSpec进行调整。
/**
* 根据甲方公钥生成乙方密钥对(含公钥、私钥)
*
* @param key 甲方公钥
* @return map
* @throws Exception 异常
*/
public Map<String, Object> initKey(byte[] key) throws Exception {
// 解析甲方公钥
final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
// 实例化密钥工厂
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 产生甲方公钥
final PublicKey aPublicKey = keyFactory.generatePublic(x509EncodedKeySpec);
// 由甲方公钥构建乙方密钥
final ECParameterSpec ecParameterSpec = ((ECPublicKey) aPublicKey).getParams();
// 初始化密钥对生成器
final KeyPairGenerator dh = KeyPairGenerator.getInstance(keyFactory.getAlgorithm());
dh.initialize(ecParameterSpec);
// 生成密钥对
final KeyPair keyPair = dh.generateKeyPair();
// 获取公钥
final PublicKey publicKey = keyPair.getPublic();
// 获取私钥
final PrivateKey privateKey = keyPair.getPrivate();
// 构造返回map
Map<String, Object> keyMap = new HashMap<>();
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
2. 典型非对称加密算法 - RSA
代码实现
public static final String KEY_ALGORITHM = "RSA";
public static final int KEY_SIZE = 512;
public static final String PUBLIC_KEY = "DHPublicKey";
public static final String PRIVATE_KEY = "DHPrivateKey";
/**
* 生成甲方密钥对(含公钥、私钥)
*
* @return map
* @throws Exception 异常
*/
public Map<String, Object> initKey() throws Exception {
// 初始化密钥对生成器
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
// 生成密钥对
final KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 获取公钥
final PublicKey publicKey = keyPair.getPublic();
// 获取私钥
final PrivateKey privateKey = keyPair.getPrivate();
// 构造返回map
Map<String, Object> keyMap = new HashMap<>();
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
* 取得公钥
*
* @param keyMap 密钥map
* @return 公钥
*/
public byte[] getPublicKey(Map<String, Object> keyMap) {
final Key key = (Key) keyMap.get(PUBLIC_KEY);
return key.getEncoded();
}
/**
* 取得私钥
*
* @param keyMap 密钥map
* @return 私钥
*/
public byte[] getPrivateKey(Map<String, Object> keyMap) {
final Key key = (Key) keyMap.get(PRIVATE_KEY);
return key.getEncoded();
}
/**
* 使用私钥加密数据
*
* @param data 待加密数据
* @param privateKey 私钥
* @return 加密后数据
*/
public byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
// 获取私钥
final PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 生成私钥
final PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
// 数据加密
final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, priKey);
return cipher.doFinal(data);
}
/**
* 使用公钥解密数据
*
* @param data 待解密数据
* @param publicKey 公钥
* @return 解密后数据
*/
public byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
// 获取公钥
final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 生成公钥
final PublicKey pubKey = keyFactory.generatePublic(x509EncodedKeySpec);
// 数据加密
final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, pubKey);
return cipher.doFinal(data);
}
/**
* 使用公钥加密数据
*
* @param data 待解密数据
* @param publicKey 公钥
* @return 解密后数据
*/
public byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
// 获取公钥
final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 生成公钥
final PublicKey pubKey = keyFactory.generatePublic(x509EncodedKeySpec);
// 数据加密
final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return cipher.doFinal(data);
}
/**
* 使用私钥解密数据
*
* @param data 待加密数据
* @param privateKey 私钥
* @return 加密后数据
*/
public byte[] decryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
// 获取私钥
final PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 生成私钥
final PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
// 数据加密
final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, priKey);
return cipher.doFinal(data);
}
@Test
public void testRSA() throws Exception {
Security.addProvider(new BouncyCastleProvider());
final Map<String, Object> aKeyMap = initKey();
final byte[] aPublicKey = getPublicKey(aKeyMap);
final byte[] aPrivateKey = getPrivateKey(aKeyMap);
System.out.println("甲方公钥:" + Base64.toBase64String(aPublicKey));
System.out.println("甲方私钥:" + Base64.toBase64String(aPrivateKey));
final byte[] aEncrypt = encryptByPrivateKey("我是阿汤哥".getBytes(), aPrivateKey);
final byte[] bDecrypt = decryptByPublicKey(aEncrypt, aPublicKey);
System.out.println("甲方:使用甲方私钥加密消息:" + Base64.toBase64String(aEncrypt));
System.out.println("乙方:使用甲方公钥解密消息:" + new String(bDecrypt));
final byte[] bEncrypt = encryptByPublicKey("Hello, 阿汤哥".getBytes(), aPublicKey);
final byte[] aDecrypt = decryptByPrivateKey(bEncrypt, aPrivateKey);
System.out.println("乙方:使用甲方公钥加密消息:" + Base64.toBase64String(bEncrypt));
System.out.println("甲方:使用甲方私钥解密消息:" + new String(aDecrypt));
}
执行结果
甲方公钥:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ7vEoMQFnSZq8tIKydTxeZQZbg3EzZ+uoqMB6xYUz0bJKTLBE2VdT8SKmhCFjyBLzRla8bCl5EtLB/S3F/isD0CAwEAAQ==
甲方私钥:MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAnu8SgxAWdJmry0grJ1PF5lBluDcTNn66iowHrFhTPRskpMsETZV1PxIqaEIWPIEvNGVrxsKXkS0sH9LcX+KwPQIDAQABAkAePbMyCP+c1BiiJ2s+omwHdMjGEoSvW9G2xwo2ut+rwo+UiKX/OXtjggNL32sOG/VBpmwQnCzhHXlM3Uf/AyLBAiEA0j02vlbqrkb4eLLTX/K1ZXk05xFMaxjCfqIdv9VwqykCIQDBhxD/jP48lN/I/cNQjg4710e46gL5U3TvDfmpXZYS9QIgYAHkRfebJAr03OmM7XwAql43cm3L3/xmlT2jKD9oPEECIBAgRh1VTVYU/bTM2Hqc67i2zqYs8cR+3M6StowTXU8FAiAp+LnIyULp1obJN9ZnLRv5RldROa9Evj94cfDq3gu+QQ==
甲方:使用甲方私钥加密消息:lK3A3bNyxV1xc34st8fOtIy5vyjTL1zm7wbU9v5mV21t0hxf1ZLTdvN5+vZPSylF3th0c0KqSdGNLpaazvEYSg==
乙方:使用甲方公钥解密消息:我是阿汤哥
乙方:使用甲方公钥加密消息:msiUhALltZYWQdpDWpp6X4wmDCR3ZVGw4d3AqYBnnwDloNDBivpBhT4LgWseX7x74GpgKFA1g/mpsKCIoXqOiw==
甲方:使用甲方私钥解密消息:Hello, 阿汤哥
3. 常用非对称加密算法 - ElGamal
代码实现
public static final String KEY_ALGORITHM = "ElGamal";
public static final int KEY_SIZE = 256;
public static final String PUBLIC_KEY = "ElGamalPublicKey";
public static final String PRIVATE_KEY = "ElGamalPrivateKey";
/**
* 生成甲方密钥对(含公钥、私钥)
*
* @return map
* @throws Exception 异常
*/
public Map<String, Object> initKey() throws Exception {
// 加入BouncyCastleProvider支持
Security.addProvider(new BouncyCastleProvider());
// 实例化算法参数生成器
final AlgorithmParameterGenerator apg = AlgorithmParameterGenerator.getInstance(KEY_ALGORITHM);
// 初始化算法生成器
apg.init(KEY_SIZE);
// 生成算法参数
final AlgorithmParameters parameters = apg.generateParameters();
// 构建参数材料
final DHParameterSpec dhParameterSpec = parameters.getParameterSpec(DHParameterSpec.class);
// 实例化密钥对生成器
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGenerator.initialize(dhParameterSpec, new SecureRandom());
// 生成密钥对
final KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 获取公钥
final PublicKey publicKey = keyPair.getPublic();
// 获取私钥
final PrivateKey privateKey = keyPair.getPrivate();
// 构造返回map
Map<String, Object> keyMap = new HashMap<>();
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
* 取得公钥
*
* @param keyMap 密钥map
* @return 公钥
*/
public byte[] getPublicKey(Map<String, Object> keyMap) {
final Key key = (Key) keyMap.get(PUBLIC_KEY);
return key.getEncoded();
}
/**
* 取得私钥
*
* @param keyMap 密钥map
* @return 私钥
*/
public byte[] getPrivateKey(Map<String, Object> keyMap) {
final Key key = (Key) keyMap.get(PRIVATE_KEY);
return key.getEncoded();
}
/**
* 使用公钥加密数据
*
* @param data 待解密数据
* @param publicKey 公钥
* @return 解密后数据
*/
public byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
Security.addProvider(new BouncyCastleProvider());
// 获取公钥
final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 生成公钥
final PublicKey pubKey = keyFactory.generatePublic(x509EncodedKeySpec);
// 数据加密
final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return cipher.doFinal(data);
}
/**
* 使用私钥解密数据
*
* @param data 待加密数据
* @param privateKey 私钥
* @return 加密后数据
*/
public byte[] decryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
Security.addProvider(new BouncyCastleProvider());
// 获取私钥
final PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
final KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 生成私钥
final PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
// 数据加密
final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, priKey);
return cipher.doFinal(data);
}
@Test
public void testRSA() throws Exception {
Security.addProvider(new BouncyCastleProvider());
final Map<String, Object> bKeyMap = initKey();
final byte[] bPublicKey = getPublicKey(bKeyMap);
final byte[] bPrivateKey = getPrivateKey(bKeyMap);
System.out.println("乙方公钥:" + Base64.toBase64String(bPublicKey));
System.out.println("乙方私钥:" + Base64.toBase64String(bPrivateKey));
final byte[] aEncrypt = encryptByPublicKey("我是阿汤哥".getBytes(), bPublicKey);
final byte[] bDecrypt = decryptByPrivateKey(aEncrypt, bPrivateKey);
System.out.println("甲方:使用乙方公钥加密消息:" + Base64.toBase64String(aEncrypt));
System.out.println("乙方:使用乙方私钥解密消息:" + new String(bDecrypt));
}
执行结果
乙方公钥:MHYwTwYGKw4HAgEBMEUCIQD3Tow0iMrSnqcab/qk3sixGNZsFqerw5TZS8AthdG9/wIgVwGItAIOERVrOUQuvYUf4iBgNedVcIVEMpmCAAF67GsDIwACICuSrF+jA6g2XGfFjtP8zmZWA0LstwQQgsMBB6AYuA1/
乙方私钥:MHgCAQAwTwYGKw4HAgEBMEUCIQD3Tow0iMrSnqcab/qk3sixGNZsFqerw5TZS8AthdG9/wIgVwGItAIOERVrOUQuvYUf4iBgNedVcIVEMpmCAAF67GsEIgIgS99qTF3QgAjIKNcpPaA5jnTSp6AUOqb1XhOGGtr75iw=
甲方:使用乙方公钥加密消息:3sdh+pOViDQWU8aDO/LC1SnK427qrFc8PHrMVyE+k7MbL7tQHbq+5I7MZ0vz7WAc6ysAvVZU9pg8YcQvoYWoEw==
乙方:使用乙方私钥解密消息:我是阿汤哥