RSA算法使用javascript加密,使用java解密,提供完整代码及例子下载。
javascript加密介绍参见另一篇:javascript使用RSA加密提交数据。本篇的例子使用的js是上一篇中提到的第2个版本。
本篇是服务端解密部分,并且提供可运行的包括js的全部示例代码。
由于sun虚拟机自带的RSA解密填充模式使用的都是特殊的PADDING模式,而js中使用的padding其实就是特殊处理的部分,实际加密时是nopadding模式,所以无法直接使用sun自带的RSA算法在服务器端解密,可以使用第3方bouncycastle提供的算法程序,最新版可以在这里下载http://www.bouncycastle.org/latest_releases.html
update:
测试时,请使用java中输出的js公钥替换test.html中的公钥。
关于性能:
第一次解密过程相对来说比较慢(几百毫秒),后续的过程都比较快,可以通过多条值测试。
关于并发:
可以通过使用多个值解密,循环创建线程来测试并发时的正确性和耗费时间。
使用过程中注意到的问题:
密钥对的值与种子、虚拟机实现等都有关系,不同的机器生成的密钥值可能不同。在实际测试时发现,同样的环境,有些机器每次生成的密钥值也不同,比如每次重启服务器后值不同。所以在实际生产环境中使用时,该值需要通过服务器端输出到客户端。如果有多台服务器,可能每台服务器的值不同,所以需要有类似F5的策略,保证多次请求路由到一台服务器上。
或者所有服务器都通过读取提前生成的证书或者私钥串来生成私钥对象,然后再进行解密。
package com.yajiao.rsa; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.Provider; import java.security.PublicKey; import java.security.SecureRandom; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.provider.JCERSAPublicKey; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Hex; public class RSABCExample { /** 可以先注册到虚拟机中,再通过名称使用;也可以不注册,直接传入使用 */ public static final Provider pro = new BouncyCastleProvider(); /** 种子,改变后,生成的密钥对会发生变化 */ private static final String seedKey = "random"; private static final String charSet = "UTF-8"; // private static String publicKeyStr = null; // private static String privateKeyStr = null; private static PrivateKey privateKey = null; private static PublicKey publicKey = null; private static String jsPublicKey = null; static{ try { generateKeyPair(); getJsPublicKey(); } catch (Exception e) { throw new RuntimeException("生成密钥对失败"); } } /** * 生成密钥对 * @throws Exception */ private static void generateKeyPair() throws Exception { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", pro); kpg.initialize(1024, new SecureRandom(seedKey.getBytes())); KeyPair kp = kpg.generateKeyPair(); privateKey = kp.getPrivate(); publicKey = kp.getPublic(); // privateKeyStr = new String(Base64.encode(privateKey.getEncoded())); // publicKeyStr = new String(Base64.encode(publicKey.getEncoded())); // System.out.println("PrivateKey:" + privateKey); // System.out.println("PublicKey:" + publicKey); // System.out.println(privateKeyStr); // System.out.println(publicKeyStr); } /** * 解密 */ public static byte[] decrypt(byte[] encrypted) throws Exception { long start = System.currentTimeMillis(); Cipher cipher = Cipher.getInstance("RSA", pro); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] re = cipher.doFinal(encrypted); long end = System.currentTimeMillis(); System.out.println("decrypt use time " + (end - start) + ""); return re; } /** * 解密js加密后的值 */ public static String decodeJsValue(String jsValue) throws Exception { byte[] input = Hex.decode(jsValue); byte[] raw = decrypt(input); // 标志位为0之后的是输入的有效字节 int i = raw.length - 1; while (i > 0 && raw[i] != 0) { i--; } i++; byte[] data = new byte[raw.length - i]; for (int j = i; j < raw.length; j++) { data[j - i] = raw[j]; } return new String(data, charSet); } /** * js加密时使用的公钥字符串 * <p><b>注意:</b> * 生成的密钥对的值与 种子(seedKey)、虚拟机实现等都有关系,不同的机器生成的密钥值可能不同。 * 在实际测试时发现,同样的环境,有些机器每次生成的密钥值也不同,比如每次重启服务器后值不同。 * 所以在实际生产环境中使用时,该值需要通过服务器端输出到客户端。 * 如果有多台服务器,可能每台服务器的值不同,所以需要有类似F5的策略,保证多次请求路由到一台服务器上。 */ public static String getJsPublicKey(){ if(jsPublicKey == null){ JCERSAPublicKey jce = (JCERSAPublicKey) publicKey; jsPublicKey = jce.getModulus().toString(16); } return jsPublicKey; } public static void main(String[] args) throws Exception { //注意:需要使用该值替换test.html中的公钥值 System.out.println("js中使用的公钥字符串" + getJsPublicKey()); // js加密后的值 String de = "08f7e292ccb4c73a981569a9c2dbf2b9c0c2cf615967282863e6e358432af288f1f026ed91a8ff5f6579ac246af9ce1f94f85e92b8a926627b95e6bd05b00b80a5548e9ce1a9bb2a20073cce629936ab9e27021af7370c2664065107a702c1805a4ec131a3573007213da3e390221053867074a427ffc28aa642fe2099ad7332"; System.out.println(decodeJsValue(de)); } //-------------------------下面方法可以不用 private void test(){ // check equals // PublicKey pb = getPublicRSAKey(publicKeyStr); // System.out.println(pb.equals(publicKey)); // PrivateKey ppk = getPrivateRSAKey(privateKeyStr); // System.out.println(ppk.equals(privateKey)); // // String input = "测试abcABC123"; // byte[] en = encrypt(input); // System.out.println(new String(Hex.encode(en))); // // byte[] re = decrypt(en); // System.out.println(new String(re, charSet)); } /** * 根据Base64编码的公钥值生成公钥对象 * <p> * 测试时使用,可以用于从证书文件中的公钥生成公钥对象。如果不涉及到证书操作,可以忽略该方法。 */ public static PublicKey getPublicRSAKey(String key) throws Exception { X509EncodedKeySpec x509 = new X509EncodedKeySpec(Base64.decode(key)); KeyFactory kf = KeyFactory.getInstance("RSA", pro); return kf.generatePublic(x509); } /** * 根据Base64编码的私钥值生成私钥对象 * <p> * 测试时使用,可以用于从证书文件中的私钥生成私钥对象。如果不涉及到证书操作,可以忽略该方法。 */ public static PrivateKey getPrivateRSAKey(String key) throws Exception { PKCS8EncodedKeySpec pkgs8 = new PKCS8EncodedKeySpec(Base64.decode(key)); KeyFactory kf = KeyFactory.getInstance("RSA", pro); return kf.generatePrivate(pkgs8); } /** * 加密 */ public static byte[] encrypt(String input) throws Exception { long start = System.currentTimeMillis(); Cipher cipher = Cipher.getInstance("RSA", pro); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] re = cipher.doFinal(input.getBytes(charSet)); long end = System.currentTimeMillis(); System.out.println("encrypt use time " + (end - start) + ""); return re; } }
相关推荐
经过本人修改,简化并完善了别人的代码,使其更加的容易理解和学习! 此为一个完整的项目,...功能:服务端随机生成密钥,JS用公钥加密,服务端用私钥解密。用到的JS加密文件是从官网下载的最新版,速度快,稳定性好!
很简单,一看就懂,用不明白可以留言,看到必回!如果加密中文js里加密之前encodeURIComponent编码一下,java用java.net.URLDecoder.decode(outputStr, "UTF-8");解码
js加密 js 解密 java加密
RSA通过javascript加密java解密
前端js加密, 后端java解密,引用项目工程里面js、java代码到自己工程里面即可,使用方便, 可以自行生成密钥
RSA非对称加密,指定一个密码种子,使用该密码种子用java生成密钥对,并把公钥分发到客户端(浏览器),保存密码种子;JS采用公钥对重要信息进行加密,然后传回后台,取出密码种子重新生成密码对,使用私钥对密文...
前后端API交互使用RSA和AES加密解密(js、Java).md
* RSA加密解密:私钥解密,公钥加密。 * RSA数字签名-俗称加签验签:私钥加签,公钥验签。 * RSA加密解密:私钥解密,公钥加密。 * RSA数字签名-俗称加签验签:私钥加签,公钥验签。 * RSA加密解密:私钥...
js前台通过RSA,DES加解密,java后台解密、加密
rsa aes 加解密 js java 前后端互通
RSA,js前台加密java后台解密
AES+RSA加密解密(js和java互通).zip AES+RSA加密解密(js和java互通).zip
rsa加密技术是js前端加密,服务端解密,很适合密文加密传输
使用JS RSA公钥加密,可使用PHP RSA私钥解密、使用PHP RSA公钥加密,可使用JS RSA私钥解密
包含js和java代码,导入项目即可使用
Js Java Rsa 加密解密,具体用法请看blog,里面包含js库,java jar包,和一个别人写的可以完成加密解密的demo
java接口数据加密解密,基于RSA原理,java与js对数据加密,解密的demo案例。 java+js基于RSA解密解密。
综合网上javasript和java RSA加密解密资源,实现了java和javascript RSA加密解密的互操作,都可以生成公钥传给对方加密然后回传密文用自己的私钥解密。