`
keepaneye
  • 浏览: 40693 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

RSA使用js加密,使用java解密

    博客分类:
  • java
阅读更多

    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;
	}	

}

 

 

 

 

 

 

分享到:
评论
5 楼 sunfeilong1993 2015-05-11  
试了一下,第110行 JCERSAPublicKey有点问题,换成BCRSAPublicKey就好了。
用的是:bcprov-ext-jdk15on-152.jar
4 楼 linuxgao 2015-04-09  
按照兄台的代码,确实是调通了,不知道这个js库有没有签名的实现?
交流以下几点:
1、在java中用sun和bc都可以实现对应的加解密
2、JS库中的padding其实就是标准的PKCS1Padding,sun和bc都有实现的
Cipher.getInstance("RSA/ECB/PKCS1Padding",pro);就省去了自己去掉填充的头了。
3 楼 keepaneye 2014-01-05  
xshdch 写道
写错了,是linux

应该还是密钥不匹配的问题,我们生产环境也是linux。
生成的密钥对的值与 种子(seedKey)、虚拟机实现等都有关系,不同的机器生成的密钥值可能不同。在实际测试时发现,同样的环境,有些机器每次生成的密钥值也不同,比如每次重启服务器后值不同。所以在实际生产环境中使用时,该值需要通过服务器端输出到客户端。
2 楼 xshdch 2013-11-20  
写错了,是linux
1 楼 xshdch 2013-11-20  
windows正常,liunx下面解密乱码,请问是什么原因

相关推荐

    RSA加密解密 JS加密 JAVA解密 【完美版】

    经过本人修改,简化并完善了别人的代码,使其更加的容易理解和学习! 此为一个完整的项目,...功能:服务端随机生成密钥,JS用公钥加密,服务端用私钥解密。用到的JS加密文件是从官网下载的最新版,速度快,稳定性好!

    前端使用jsencrypt加密后端使用java RSA解密功能实现源码

    本文将详细介绍一个实际案例:如何在前端使用JavaScript库`jsencrypt`进行RSA加密,并在后端使用Java进行解密。这个功能实现的核心知识点包括RSA算法、`jsencrypt`库的使用以及前后端的交互。 首先,RSA是一种非...

    rsa加密 js加密 java解密

    在"rsa加密_js加密_java解密"的场景中,我们首先在前端(通常是浏览器环境)使用JavaScript实现RSA加密。JS库如CryptoJS或Forge提供了RSA加密的功能,可以将待保护的数据转化为密文。这个过程可能涉及将数据分割成...

    前后端API交互使用RSA和AES加密解密(js、Java).md

    前后端API交互使用RSA和AES加密解密(js、Java).md

    aes、ras,前端js加密,后端java解密

    在前端,可以使用`jsencrypt`库进行RSA加密,后端使用Java的`java.security`包中的`RSAPublicKey`和`RSAPrivateKey`进行解密。 **JavaScript加密实现** 在前端,`jsencrypt.js`库提供了RSA加密功能,可以方便地将...

    RSA通过javascript加密java解密

    在“RSA通过javascript加密java解密”的场景中,我们有两个主要的技术点:JavaScript端的加密和Java端的解密。以下是对这两个环节的详细说明: 1. JavaScript端的RSA加密: - 使用库:JavaScript中常见的RSA加密库...

    js前台通过RSA,DES加解密,java后台解密、加密

    在JavaScript中,可以使用库如`crypto-js`来实现DES加密,而Java则有内置的`javax.crypto`包,提供了对DES加密的支持。前端与后端之间,通常通过HTTP或HTTPS协议进行通信,HTTPS能提供基本的传输层安全,但为了...

    RSA-JS加密,JAVA解密实例

    总之,RSA-JS加密和JAVA解密实例展示了非对称加密技术在实际应用中的工作流程,提供了前端加密和后端解密的一种解决方案,确保了敏感信息在传输过程中的安全性。在实际项目中,可以根据需求选择合适的库和工具来实现...

    java_RSA2048加密解密.zip

    总结,这个压缩包提供的Java RSA2048加密解密示例涵盖了前端JavaScript和后端Java的实现,旨在帮助开发者快速集成这一安全机制。正确理解和应用这些代码,可以提高应用程序的数据安全性,防止数据在传输过程中被窃取...

    RSA,JS加密java解密

    很简单,一看就懂,用不明白可以留言,看到必回!如果加密中文js里加密之前encodeURIComponent编码一下,java用java.net.URLDecoder.decode(outputStr, "UTF-8");解码

    关于使用JS前台加密、JAVA后台解密的RSA实现,RSA加密和签名

    这篇博文"关于使用JS前台加密、JAVA后台解密的RSA实现,RSA加密和签名"探讨了如何在JavaScript前端进行RSA加密,并在Java后端进行解密,以及如何使用RSA进行数字签名。 RSA加密的核心在于一对公钥和私钥。公钥用于...

    传输密码加密:rsa实现js前台加密java后台解密

    源码的应用场景: ...这样客户端只需要知道rsa加密方式和公钥,前台不知道私钥是无法解密的,此解决方案还是相对比较安全的。 使用源码的注意事项: http://blog.csdn.net/wu_jia123/article/details/50553128

    java js RSA加密支持超长加密

    在JavaScript中,没有内置的RSA加密库,但可以使用第三方库,如`node-rsa`或`crypto-js`。这些库提供了类似的公钥/私钥生成和加密/解密功能。需要注意的是,由于JavaScript环境的安全限制,浏览器端可能无法直接处理...

    RSA加密解密之javascript与java配套源码.zip

    在提供的压缩包中,有两个Java文件(RSACrypt.java和RSACryptTest.java)和一个JavaScript文件(jsencrypt.min.js),这表明代码实现了RSA加密解密的Java版本和JavaScript版本,可以在客户端和服务端之间进行安全的...

    rsa加密(js加密java解密)

    2. **前端加密**:前端接收到公钥后,使用JavaScript库(如`crypto-js`或`jsrsasign`)将需要加密的数据与公钥一起进行RSA加密。 3. **数据传输**:加密后的密文通过网络发送到服务器。 4. **服务器解密**:服务器...

    RSA加密解密(JS加密JAVA解密)

    RSA非对称加密,指定一个密码种子,使用该密码种子用java生成密钥对,并把公钥分发到客户端(浏览器),保存密码种子;JS采用公钥对重要信息进行加密,然后传回后台,取出密码种子重新生成密码对,使用私钥对密文...

    Js Java Rsa 加密解密

    例如,前端可以使用JavaScript库加密用户数据,然后通过HTTP请求发送到后端,后端使用Java解密数据,进行后续处理。这种方法有助于保护用户隐私,防止中间人攻击,确保数据在传输过程中的安全性。 需要注意的是,...

Global site tag (gtag.js) - Google Analytics