非对称加密算法中,提供一个公钥一个私钥。一般情况下,采用公钥加密、私钥解密的方式。
假设有这样一个场景:服务A与服务B需要通信,通信内容为了安全需要进行加密传输,并且服务A与服务B不能互相持有对方的钥匙。
我首先想到的是能否利用RSA实现双向的加解密,查阅了资料后做了一个简单的实现,下面贴出实现原理及代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
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 明文数据 */ 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("明文数据已损坏",e); } catch (Exception e) { throw new RSAException("未知错误",e); } } /** * 私钥解密 * * @param privateKey 私钥 * @param content 密文数据 */ 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("密文数据已损坏",e); } catch (Exception e) { e.printStackTrace(); throw new RSAException("未知错误",e); } } /** * 私钥加密 * * @param privateKey 私钥 * @param content 明文数据 */ 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("明文数据已损坏",e); } } /** * 公钥解密 * * @param publicKey 公钥 * @param content 密文数据 */ 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("密文数据已损坏",e); } } } |
from:https://blog.csdn.net/qq_42014561/article/details/128385886