mirror of
https://github.com/RemainderTime/spring-boot-base-demo.git
synced 2026-06-04 00:47:46 +08:00
- 在login.html中添加HTML语言声明和密码显示功能 - 重构前端RSA加密逻辑,支持大数据块分片加密 - 更新RSAUtils.java中的加密算法,使用标准PKCS1填充模式 - 移除UserService中不必要的BCryptPasswordEncoder依赖 - 简化success.html页面的参数解析逻辑 - 统一前后端RSA加密解密的实现方式
135 lines
5.5 KiB
Java
135 lines
5.5 KiB
Java
package cn.xf.basedemo.common.utils;
|
|
|
|
import javax.crypto.Cipher;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.security.KeyFactory;
|
|
import java.security.KeyPair;
|
|
import java.security.KeyPairGenerator;
|
|
import java.security.PrivateKey;
|
|
import java.security.PublicKey;
|
|
import java.security.interfaces.RSAPrivateKey;
|
|
import java.security.interfaces.RSAPublicKey;
|
|
import java.security.spec.InvalidKeySpecException;
|
|
import java.security.spec.PKCS8EncodedKeySpec;
|
|
import java.security.spec.X509EncodedKeySpec;
|
|
import java.util.Base64;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
public class RSAUtils {
|
|
|
|
private static final String RSA = "RSA";
|
|
private static final String RSA_TRANSFORMATION = "RSA/ECB/PKCS1Padding";
|
|
private static final int KEY_SIZE = 1024;
|
|
|
|
private static Map<String, String> createEncryptKey() {
|
|
try {
|
|
KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
|
|
kpg.initialize(KEY_SIZE);
|
|
KeyPair keyPair = kpg.generateKeyPair();
|
|
|
|
PublicKey publicKey = keyPair.getPublic();
|
|
PrivateKey privateKey = keyPair.getPrivate();
|
|
|
|
Map<String, String> map = new HashMap<>();
|
|
map.put("publicKey", Base64.getEncoder().encodeToString(publicKey.getEncoded()));
|
|
map.put("privateKey", Base64.getEncoder().encodeToString(privateKey.getEncoded()));
|
|
return map;
|
|
} catch (Exception e) {
|
|
throw new IllegalArgumentException("create RSA key pair failed", e);
|
|
}
|
|
}
|
|
|
|
public static RSAPublicKey getPublicKey(String publicKeyStr) throws InvalidKeySpecException {
|
|
try {
|
|
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
|
|
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodeBase64(publicKeyStr));
|
|
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
|
|
} catch (InvalidKeySpecException e) {
|
|
throw e;
|
|
} catch (Exception e) {
|
|
throw new InvalidKeySpecException("invalid RSA public key", e);
|
|
}
|
|
}
|
|
|
|
public static RSAPrivateKey getPrivateKey(String privateKeyStr) throws InvalidKeySpecException {
|
|
try {
|
|
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
|
|
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodeBase64(privateKeyStr));
|
|
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
|
|
} catch (InvalidKeySpecException e) {
|
|
throw e;
|
|
} catch (Exception e) {
|
|
throw new InvalidKeySpecException("invalid RSA private key", e);
|
|
}
|
|
}
|
|
|
|
public static String publicEncrypt(String data, RSAPublicKey publicKey) {
|
|
try {
|
|
Cipher cipher = Cipher.getInstance(RSA_TRANSFORMATION);
|
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
|
byte[] encrypted = rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE,
|
|
data.getBytes(StandardCharsets.UTF_8), publicKey.getModulus().bitLength());
|
|
return Base64.getEncoder().encodeToString(encrypted);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException("RSA encrypt failed", e);
|
|
}
|
|
}
|
|
|
|
public static String privateDecryption(String data, RSAPrivateKey privateKey) {
|
|
try {
|
|
Cipher cipher = Cipher.getInstance(RSA_TRANSFORMATION);
|
|
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
|
byte[] decrypted = rsaSplitCodec(cipher, Cipher.DECRYPT_MODE,
|
|
decodeBase64(data), privateKey.getModulus().bitLength());
|
|
return new String(decrypted, StandardCharsets.UTF_8);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException("RSA decrypt failed", e);
|
|
}
|
|
}
|
|
|
|
private static byte[] decodeBase64(String data) {
|
|
String normalizedData = data.replaceAll("\\s", "");
|
|
try {
|
|
return Base64.getDecoder().decode(normalizedData);
|
|
} catch (IllegalArgumentException e) {
|
|
return Base64.getUrlDecoder().decode(normalizedData);
|
|
}
|
|
}
|
|
|
|
private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
|
|
int maxBlock = opmode == Cipher.DECRYPT_MODE ? keySize / 8 : keySize / 8 - 11;
|
|
int offset = 0;
|
|
int index = 0;
|
|
|
|
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
|
while (datas.length > offset) {
|
|
int inputLen = Math.min(datas.length - offset, maxBlock);
|
|
byte[] buffer = cipher.doFinal(datas, offset, inputLen);
|
|
out.write(buffer, 0, buffer.length);
|
|
index++;
|
|
offset = index * maxBlock;
|
|
}
|
|
return out.toByteArray();
|
|
} catch (Exception e) {
|
|
throw new RuntimeException("RSA block codec failed, maxBlock=" + maxBlock, e);
|
|
}
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
Map<String, String> encryptKey = createEncryptKey();
|
|
String publicKey = encryptKey.get("publicKey");
|
|
String privateKey = encryptKey.get("privateKey");
|
|
|
|
String data = "{\"account\":\"admin\",\"pwd\":\"123456\"}";
|
|
String encrypted = publicEncrypt(data, getPublicKey(publicKey));
|
|
String decrypted = privateDecryption(encrypted, getPrivateKey(privateKey));
|
|
|
|
System.out.println("publicKey: " + publicKey);
|
|
System.out.println("privateKey: " + privateKey);
|
|
System.out.println("encrypted: " + encrypted);
|
|
System.out.println("decrypted: " + decrypted);
|
|
}
|
|
}
|