一、应用场景 源码下载
前端登录账户加密
后端解密
二、
1、生成 模hex、公钥指数hex 私钥指数hex
KeyPair keyPair = genRSAKeyPair();
//生成公钥和私钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
//模hex
String modulus = publicKey.getModulus().toString(16);
//公钥指数hex
String public_exponent = publicKey.getPublicExponent().toString(16);
//私钥指数hex
String private_exponent = privateKey.getPrivateExponent().toString(16);
2、后端
private static final int MAX_ENCRYPT_BLOCK = 117; // RSA最大加密明文大小
private static final int MAX_DECRYPT_BLOCK = 128; // RSA最大解密密文大小
public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int inputLen = data.length;
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
return out.toByteArray();
}
}
public static byte[] decryptByPrivateKey(byte[] encryptedData, RSAPrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
int inputLen = encryptedData.length;
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
return out.toByteArray();
}
}
//使用模和指数生成公钥和私钥
RSAPublicKey pubKey = getPublicKey(modulus, public_exponent);
RSAPrivateKey priKey = getPrivateKey(modulus, private_exponent);
String = plaintStr="学而不思则罔,思而不学则殆";
//公钥加密后的密文
byte[] encryptStr = encryptByPublicKey(plaintStr.getBytes("utf-8"), pubKey);
//工具类后面写
System.out.println("加密后的密文: " + HexUtil.bytesToHexString(encryptStr));
//私钥解密后的明文
//js加密的密文传过来时是十六进制byte数组的String格式的 转换byte[] 工具hex2byte(String hex)
byte[] decryptStr = decryptByPrivateKey(encryptStr, priKey);
System.out.println("解密后: " + new String(decryptStr, "utf-8"));
public static String bytesToHexString(byte[] src){
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
/**
* 十六进制byte数组转二进制byte数组
* hex to byte array
*
* @param hex hex string
* @return byte array
*/
public static byte[] hex2byte(String hex)
throws IllegalArgumentException{
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException ("invalid hex string");
}
char[] arr = hex.toCharArray();
byte[] b = new byte[hex.length() / 2];
for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
String swap = "" + arr[i++] + arr[i];
int byteint = Integer.parseInt(swap, 16) & 0xFF;
b[j] = new Integer(byteint).byteValue();
}
return b;
}
3、前端
<script language="JavaScript" type="text/javascript" src="http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js"></script>
<script language="JavaScript" type="text/javascript" src="http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn2.js"></script>
<script language="JavaScript" type="text/javascript" src="http://www-cs-students.stanford.edu/~tjw/jsbn/prng4.js"></script>
<script language="JavaScript" type="text/javascript" src="http://www-cs-students.stanford.edu/~tjw/jsbn/rng.js"></script>
<script language="JavaScript" type="text/javascript" src="http://www-cs-students.stanford.edu/~tjw/jsbn/rsa.js"></script>
<script language="JavaScript" type="text/javascript" src="http://www-cs-students.stanford.edu/~tjw/jsbn/rsa2.js"></script>
<script type="text/javascript">
// 这个是后台生成并返回的RSA信息(公钥) 将后台生成的公钥拿到前面
var RSADo = {"modulus":"d4efd1b4c812f563ffd103ab89c1fded794f4c62db07cb546e2456c8de9fd11cd31dc3c2ec7e3799ead6c1fc4c6dedc331dd682b66c96d5d5d539b19c9ad69745984f729afe092592c7de5cb60a11229e42a2b8ea177c3e00e517a28963fd34007929c83db2419050edb6f7b80d3d9736f853ffdb37efabeb3f2d784026e8469",
"public_exponent":"10001"}
//private_exponent
var privateKey = "d2ae91d387ddd233e5e99cf2fd731655ff1fe99929d3b5674d2ee13b0fa21ad9a53c9ef35ee0a70cc0214a7fe1f3263b6a3c019467b7c66089356e917e4cf8b71a453480ad093303d970aff5782a1ad6f43fff7340eb78f1f356e24a0e0903fc8b0f844ebfd2c1741fa521ea54e837db8dc74a92cd40b287371b42ff9a6fa231"
// 加密:要测试的明文数据
var str = '学而不思则罔,思而不学则殆'
// 实例化js的RSA对象生成
var rsa = new RSAKey()
rsa.setPublic(RSADo.modulus, RSADo.publicExponent)
var encryptStr = rsa.encrypt(str);
console.log('RSADo', JSON.stringify(RSADo))
console.log('明文(explain):', str)
console.log('加密后(encrypt):', encryptStr)
// 解密
rsa.setPrivate(RSADo.modulus, RSADo.publicExponent, privateKey)
var decryptStr = rsa.decrypt(encryptStr)
console.log('解密私钥:', privateKey)
console.log('解密后(decrypt)', decryptStr)
</script>