JS加密、JAVA解密,有两条路:
- 根据jsencrypt步骤,使用bash命令生成公钥和私钥;
- 使用Java 代码生成公钥和私钥;
先看下第二种方式如何实现:
- 项目中运行RasUtils工具类,生成公钥和私钥,并进行下测试
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import java.io.IOException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RSAUtils {
//生成秘钥对
public static KeyPair getKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
}
//获取公钥(Base64编码)
static String getPublicKey(KeyPair keyPair) {
PublicKey publicKey = keyPair.getPublic();
byte[] bytes = publicKey.getEncoded();
return new BASE64Encoder().encode((bytes));
}
//获取私钥(Base64编码)
static String getPrivateKey(KeyPair keyPair) {
PrivateKey privateKey = keyPair.getPrivate();
byte[] bytes = privateKey.getEncoded();
return new BASE64Encoder().encode((bytes));
}
//将Base64编码后的公钥转换成PublicKey对象
static PublicKey string2PublicKey(String pubStr) throws Exception {
byte[] keyBytes = new BASE64Decoder().decodeBuffer((pubStr));
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpec);
}
//将Base64编码后的私钥转换成PrivateKey对象
static PrivateKey string2PrivateKey(String priStr) throws Exception {
byte[] keyBytes = new BASE64Decoder().decodeBuffer((priStr));
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(keySpec);
}
//公钥加密
public static String publicEncrypt(String content, String publicKeyStr) throws Exception {
PublicKey publicKey = RSAUtils.string2PublicKey(publicKeyStr);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] bytes = cipher.doFinal(content.getBytes());
return new BASE64Encoder().encode(bytes);
}
//私钥解密
public static byte[] privateDecrypt(String content, String privateKeyStr) throws Exception {
PrivateKey privateKey = RSAUtils.string2PrivateKey(privateKeyStr);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] bytes = cipher.doFinal(new BASE64Decoder().decodeBuffer(content));
return bytes;
}
public static void main(String[] args) {
try {
//===============生成公钥和私钥,公钥传给客户端,私钥服务端保留==================
KeyPair keyPair = RSAUtils.getKeyPair();
String publicKeyStr = RSAUtils.getPublicKey(keyPair);
String privateKeyStr = RSAUtils.getPrivateKey(keyPair);
System.out.println("RSA公钥Base64编码:" + publicKeyStr);
System.out.println("RSA私钥Base64编码:" + privateKeyStr);
//=================开始加密=================
String message = "panda";
//用公钥加密
String publicEncrypt = RSAUtils.publicEncrypt(message, publicKeyStr);
System.out.println("公钥加密并Base64编码的结果:" + publicEncrypt);
//===================开始解密================
//用私钥解密
byte[] privateDecrypt = RSAUtils.privateDecrypt(publicEncrypt, privateKeyStr);
//解密后的明文
System.out.println("解密后的明文: " + new String(privateDecrypt));
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行这个工具类可以看到对字符串加密解密成功;从输出中截取公钥和私钥;
公钥存储在JS端,供JS加密使用;
私钥保存在Java后端,供解密用;
- 编写HTML页面进行字符串加密
<!doctype html>
<html>
<head>
<title>JavaScript RSA Encryption</title>
<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script src="去github中下载jsencrypt.js"></script>
<script type="text/javascript">
// Call this code when the page is done loading.
$(function() {
// Run a quick encryption/decryption when they click.
$('#testme').click(function() {
// Encrypt with the public key...
var encrypt = new JSEncrypt();
encrypt.setPublicKey('刚才Java生成的公钥');
var encrypted = encrypt.encrypt('要加密的内容');
console.log(encrypted);
});
});
</script>
</head>
<body>
</body>
</html>
页面加载完毕,就会在控制台输出加密后的字符串;你可以使用该加密串返回到java中,进行解密来验证.
到此为止,基本可以实现前端RSA加密,后端RSA解密了;
再来看下实现方法一
- 我们按照jsencrypt github中的步骤,一步一步使用bash生成公钥和私钥
1.1 openssl genrsa -out rsa_1024_priv.pem 1024
1.2 cat rsa_1024_priv.pem #输出私钥
1.3 openssl rsa -pubout -in rsa_1024_priv.pem -out rsa_1024_pub.pem
1.4 cat rsa_1024_pub.pem #输出公钥
1.5 使用github中下一步的html进行验证,也可以成功(代码略,大家可自行去github中查看) - 在ResUtils中使用刚才生成的公钥进行解密,很大几率会抛出异常
algid parse error, not a sequence
- 原因:私钥在使用前为pkcs1格式,而java在不引用第三方包的情况下无法直接使用pkcs1格式的秘钥,需要将其转化为pkcs8编码
- 解决方案:
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -out rsa_private_key_01.pem -nocrypt
使用rsa_private_key_01.pem中的秘钥即可