/*
* @description: 将普通的publicKey转化得到一个RSAPublicKey
* @author: zkw
* @date: 2024/1/24 16:17
* @param: publicKey 普通的publicKey
* @return: RSAPublicKey 得到一个新的RSAPublicKey
**/
public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
//通过X509编码的Key指令获得公钥对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
return key;
}
/*
* @description: 将明文字符串利用RSAPublicKey公钥加密成一个密文
* @author: zkw
* @date: 2024/1/24 16:24
* @param: data 待加密的明文字符串
* @param: publicKey RSAPublicKey
* @return: String 密文字符串
**/
public static String publicEncrypt(String data, RSAPublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
} catch (Exception e) {
throw new RuntimeException("error......", e);
}
}
/*
* @description: 将普通的privateKey转化得到一个RSAPrivateKey
* @author: zkw
* @date: 2024/1/24 16:41
* @param: privateKey 普通的privateKey
* @return: RSAPrivateKey 得到一个新的RSAPrivateKey
**/
public static RSAPrivateKey getPrivateKey(String privateKey) {
// 通过PKCS#8编码的Key指令获得私钥对象
KeyFactory keyFactory;
RSAPrivateKey rsaPrivateKey;
try {
keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
rsaPrivateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
} catch (Exception e) {
throw new ServiceException(Codes.PASSWORD_DECRYPTION_EXCEPTION);
}
return rsaPrivateKey;
}
/*
* @description: 将密文使用私钥进行解密 解密出明文
* @author: zkw
* @date: 2024/1/24 16:42
* @param: cipherText 密文
* @param: privateKey RSAPrivateKey私钥
* @return: String 明文
**/
private static String privateDecrypt(String cipherText, RSAPrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(cipherText), privateKey.getModulus().bitLength()), CHARSET);
} catch (Exception e) {
throw new ServiceException(Codes.PASSWORD_DECRYPTION_EXCEPTION);
}
}
rsaSplitCodec()方法
private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
int maxBlock = 0;
if (opmode == Cipher.DECRYPT_MODE) {
maxBlock = keySize / 8;
} else {
maxBlock = keySize / 8 - 11;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] buff;
int i = 0;
try {
while (datas.length > offSet) {
if (datas.length - offSet > maxBlock) {
buff = cipher.doFinal(datas, offSet, maxBlock);
} else {
buff = cipher.doFinal(datas, offSet, datas.length - offSet);
}
out.write(buff, 0, buff.length);
i++;
offSet = i * maxBlock;
}
} catch (Exception e) {
e.printStackTrace();
}
byte[] resultDatas = out.toByteArray();
IOUtils.closeQuietly(out);
return resultDatas;
}
四个方法我直接贴出来,两个方法是关于公钥的,两个方法是关于私钥的
我们写一个测试方法,看看明文加密之后的密文,在经过解密后的明文是否一致。
public static void method(String clearPassword) throws NoSuchAlgorithmException, InvalidKeySpecException {
//【前端通过js】 1、生成一个普通的PublicKey,一般这里前端会生成,同时也需要转化成一个RSAPublicKey,然后再对输入的明文字符串进行加密成一个密文,这里我不知道前端怎么写,我们就以后端的思路去代替
KeyPair keyPair = KeyPairGenerator.getInstance(RSA_ALGORITHM).generateKeyPair();
String publicKey = new String(java.util.Base64.getEncoder().encode(keyPair.getPublic().getEncoded()));
RSAPublicKey rsaPublicKey = getPublicKey(publicKey);
String cipherText = publicEncrypt(clearPassword, rsaPublicKey);//密文字符串
//【后端通过代码】2、生成一个普通的PrivateKey
String privateKey = new String(java.util.Base64.getEncoder().encode(keyPair.getPrivate().getEncoded()));
// //3、将普通的privateKey转化为一个新的RSAPrivateKey
RSAPrivateKey rsaPrivateKey = getPrivateKey(privateKey);
//
// //4、对前端传过来的密文利用RSA私钥进行解密
String res = privateDecrypt(cipherText, rsaPrivateKey);
System.out.println("加密之前的明文:" + clearPassword);
System.out.println("加密之后的密文:" + cipherText);
System.out.println("================================");
System.out.println("解密之后的明文:" + res);
}
运行结果:
所以以后在登录的时候呢,前端会对界面输入的明文密码进行公钥加密成密文密码,然后再传给后端,后端就会利用私钥进行解密解密出明文密码,然后与数据库的进行比较。
总结:
使用java.security包下的api进行密码的加密传输(公加私解)
给大家画个流程图:
最后:
如果大家觉得这篇文章对大家有所帮助的话,希望能给个免费的赞赞,也祝各位码农在未来的IT道路上能越走越远。谢谢。