??????? 非對稱加密算法中,提供一個公鑰一個私鑰。一般情況下,采用公鑰加密、私鑰解密的方式。
??????? 假設有這樣一個場景:服務A與服務B需要通信,通信內容為了安全需要進行加密傳輸,并且服務A與服務B不能互相持有對方的鑰匙。文章來源:http://www.zghlxwxcb.cn/news/detail-510925.html
??????? 我首先想到的是能否利用RSA實現(xiàn)雙向的加解密,查閱了資料后做了一個簡單的實現(xiàn),下面貼出實現(xiàn)原理及代碼:文章來源地址http://www.zghlxwxcb.cn/news/detail-510925.html
public class RsaEncryptUtil{
public static final String PUBLIC_KEY="publicKey";
public static final String PRIVATE_KEY="privateKey";
private static final String KEY_STORE = "JKS";
private static final int MAX_ENCRYPT_LENGTH = 117;
private static final int MAX_DECRYPT_LENGTH = 128;
/**
* 隨機生成RAS公鑰與私鑰字符串,直接返回
*/
public static Map<String, String> getKeys() {
KeyPairGenerator keyPairGen;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RSAException("RSA獲取鑰匙對失敗", e);
}
// 初始化密鑰對生成器,密鑰大小為96-1024位
keyPairGen.initialize(1024,new SecureRandom());
// 生成一個密鑰對,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
Map<String,String> keyMap = new HashMap<>();
keyMap.put(PUBLIC_KEY, RSACryptUtil.base64ToStr(keyPair.getPublic().getEncoded()));
keyMap.put(PRIVATE_KEY, RSACryptUtil.base64ToStr(keyPair.getPrivate().getEncoded()));
return keyMap;
}
/**
* 獲得KeyStore
*
* @param keyStorePath
* @param password
*/
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獲得私鑰
*
* @param keyStorePath KeyStore路徑
* @param alias 別名
* @param storePass KeyStore訪問密碼
* @param keyPass 私鑰的鑰匙密碼
*/
private static PrivateKey loadPrivateKey(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獲得公鑰
*
* @param keyStorePath KeyStore路徑
* @param alias 別名
* @param storePass KeyStore訪問密碼
*/
private static PublicKey loadPublicKey(String keyStorePath, String alias, String storePass) throws Exception {
KeyStore ks = getKeyStore(keyStorePath, storePass);
PublicKey key = ks.getCertificate(alias).getPublicKey();
return key;
}
/**
* 公鑰加密
*
* @param publicKey 公鑰
* @param content 明文數(shù)據(jù)
*/
public static String encryptByPublic(String publicKey, String content){
if (StringUtils.isEmpty(publicKey)) {
throw new RSAException("加密公鑰為空, 請設置");
}
if(StringUtils.isEmpty(content)){
throw new RSAException("加密明文為空, 請設置");
}
Cipher cipher;
StringBuilder result = new StringBuilder();
try {
// 使用默認RSA
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, RSACryptUtil.loadPublicKey(publicKey));
byte[] bytes = content.getBytes();
for (int i = 0; i < bytes.length; i += MAX_ENCRYPT_LENGTH) {
byte[] subarray = ArrayUtils.subarray(bytes, i, i + MAX_ENCRYPT_LENGTH);
if(subarray != null && subarray.length > 0){
byte[] doFinal = cipher.doFinal(subarray);
result.append(RSACryptUtil.base64ToStr(doFinal));
}
}
return result.toString();
} catch (NoSuchAlgorithmException e) {
throw new RSAException("無此加密算法",e);
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return null;
} catch (InvalidKeyException e) {
throw new RSAException("加密公鑰非法,請檢查",e);
} catch (IllegalBlockSizeException e) {
throw new RSAException("明文長度非法",e);
} catch (BadPaddingException e) {
throw new RSAException("明文數(shù)據(jù)已損壞",e);
} catch (Exception e) {
throw new RSAException("未知錯誤",e);
}
}
/**
* 私鑰解密
*
* @param privateKey 私鑰
* @param content 密文數(shù)據(jù)
*/
public static String decryptByPrivate(String privateKey, String content){
if (StringUtils.isEmpty(privateKey)) {
throw new RSAException("解密私鑰為空, 請設置");
}
if(StringUtils.isEmpty(content)){
throw new RSAException("解密密文為空, 請設置");
}
if(content.length() < 4){
throw new RSAException("解密密文有誤:" + content);
}
Cipher cipher;
StringBuilder result = new StringBuilder();
try {
// 使用默認RSA
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, RSACryptUtil.loadPrivateKey(privateKey));
byte[] bytes = RSACryptUtil.strToBase64(content);
for (int i = 0; i < bytes.length; i += MAX_DECRYPT_LENGTH) {
byte[] subarray = ArrayUtils.subarray(bytes, i, i + MAX_DECRYPT_LENGTH);
if(subarray != null && subarray.length > 0){
byte[] doFinal = cipher.doFinal(subarray);
result.append(new String(doFinal));
}
}
return result.toString();
} catch (NoSuchAlgorithmException e) {
throw new RSAException("無此解密算法",e);
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return null;
} catch (InvalidKeyException e) {
throw new RSAException("解密私鑰非法,請檢查");
} catch (IllegalBlockSizeException e) {
throw new RSAException("密文長度非法",e);
} catch (BadPaddingException e) {
throw new RSAException("密文數(shù)據(jù)已損壞",e);
} catch (Exception e) {
e.printStackTrace();
throw new RSAException("未知錯誤",e);
}
}
/**
* 私鑰加密
*
* @param privateKey 私鑰
* @param content 明文數(shù)據(jù)
*/
public static String encryptByPrivate(String privateKey,String content){
if (StringUtils.isEmpty(privateKey)) {
throw new RSAException("加密私鑰為空, 請設置");
}
if(StringUtils.isEmpty(content)){
throw new RSAException("加密明文為空, 請設置");
}
Cipher cipher;
StringBuilder result = new StringBuilder();
try {
// 使用默認RSA
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, RSACryptUtil.loadPrivateKey(privateKey));
byte[] bytes = content.getBytes();
for (int i = 0; i < bytes.length; i += MAX_ENCRYPT_LENGTH) {
byte[] subarray = ArrayUtils.subarray(bytes, i, i + MAX_ENCRYPT_LENGTH);
if(subarray != null && subarray.length > 0){
byte[] doFinal = cipher.doFinal(subarray);
result.append(RSACryptUtil.base64ToStr(doFinal));
}
}
return result.toString();
}catch (NoSuchAlgorithmException e) {
throw new RSAException("無此加密算法",e);
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return null;
} catch (InvalidKeyException e) {
throw new RSAException("加密私鑰非法,請檢查",e);
} catch (IllegalBlockSizeException e) {
throw new RSAException("明文長度非法",e);
} catch (BadPaddingException e) {
throw new RSAException("明文數(shù)據(jù)已損壞",e);
}
}
/**
* 公鑰解密
*
* @param publicKey 公鑰
* @param content 密文數(shù)據(jù)
*/
public static String decryptByPublic(String publicKey, String content){
if (StringUtils.isEmpty(publicKey)) {
throw new RSAException("解密公鑰為空, 請設置");
}
if(StringUtils.isEmpty(content)){
throw new RSAException("解密密文為空, 請設置");
}
if(content.length() < 4){
throw new RSAException("解密密文有誤:" + content);
}
Cipher cipher;
StringBuilder result = new StringBuilder();
try {
// 使用默認RSA
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, RSACryptUtil.loadPublicKey(publicKey));
byte[] bytes = RSACryptUtil.strToBase64(content);
for (int i = 0; i < bytes.length; i += MAX_DECRYPT_LENGTH) {
byte[] subarray = ArrayUtils.subarray(bytes, i, i + MAX_DECRYPT_LENGTH);
if(subarray != null && subarray.length > 0){
byte[] doFinal = cipher.doFinal(subarray);
result.append(new String(doFinal));
}
}
return result.toString();
}catch (NoSuchAlgorithmException e) {
throw new RSAException("無此解密算法",e);
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return null;
} catch (InvalidKeyException e) {
throw new RSAException("解密公鑰非法,請檢查",e);
} catch (IllegalBlockSizeException e) {
throw new RSAException("密文長度非法",e);
} catch (BadPaddingException e) {
throw new RSAException("密文數(shù)據(jù)已損壞",e);
}
}
}
到了這里,關于RSA雙向加解密(公鑰加密-私鑰解密;私鑰加密-公鑰解密)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!