JavaWeb RSA加密使用小解
不管明文长度是多少,RSA 生成的密文长度总是固定的。
但是明文长度不能超过密钥长度。比如 Java 默认的 RSA 加密实现不允许明文长度超过密钥长度减去 11(单位是字节,也就是 byte)。也就是说,如果我们定义的密钥(我们可以通过 java.security.KeyPairGenerator.initialize(int keysize) 来定义密钥长度)长度为 1024(单位是位,也就是 bit),生成的密钥长度就是 1024位 / 8位/字节 = 128字节,那么我们需要加密的明文长度不能超过 128字节 -
11 字节 = 117字节。也就是说,我们最大能将 117 字节长度的明文进行加密,否则会出问题(抛诸如 javax.crypto.IllegalBlockSizeException:Data must not be longer than 53 bytes 的异常)。
String modulus = publicKey.getModulus().toString(16);
String pubexp =publicKey.getPublicExponent().toString(16);
String priexp =privateKey.getPrivateExponent().toString(16);
注意需要使用16进制下发到客户端
package com.inphase.demo.utils;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
importjava.security.NoSuchAlgorithmException;
import java.security.Security;
importjava.security.interfaces.RSAPrivateKey;
importjava.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.HashMap;
import javax.crypto.Cipher;
importorg.bouncycastle.jce.provider.BouncyCastleProvider;
public class RSAUtils {
/**
* 加密算法RSA
*/
publicstatic final String KEY_ALGORITHM = "RSA";
/**
* 签名算法
*/
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
/**
* 生成公钥和私钥
*
* @throws NoSuchAlgorithmException
*
*/
publicstatic HashMap<String, Object> getKeys()
throwsNoSuchAlgorithmException {
Security.addProvider(newBouncyCastleProvider());
HashMap<String,Object> map = new HashMap<String, Object>();
KeyPairGeneratorkeyPairGen = KeyPairGenerator.getInstance("RSA",
newBouncyCastleProvider());
keyPairGen.initialize(1024);
KeyPairkeyPair = keyPairGen.generateKeyPair();
RSAPublicKeypublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKeyprivateKey = (RSAPrivateKey) keyPair.getPrivate();
map.put("public",publicKey);
map.put("private",privateKey);
returnmap;
}
/**
* 使用模和指数生成RSA公钥
*
* @param modulus
* 模
* @param exponent
* 指数
* @return
*/
publicstatic RSAPublicKey getPublicKey(String modulus, String exponent) {
Security.addProvider(newBouncyCastleProvider());
try{
BigIntegerb1 = new BigInteger(modulus);
BigIntegerb2 = new BigInteger(exponent);
KeyFactorykeyFactory = KeyFactory.getInstance("RSA",
newBouncyCastleProvider());
RSAPublicKeySpeckeySpec = new RSAPublicKeySpec(b1, b2);
return(RSAPublicKey) keyFactory.generatePublic(keySpec);
}catch (Exception e) {
e.printStackTrace();
returnnull;
}
}
/**
* 使用模和指数生成RSA私钥 /None/NoPadding
*
* @param modulus
* 模
* @param exponent
* 指数
* @return
*/
publicstatic RSAPrivateKey getPrivateKey(String modulus, String exponent) {
try{
Security.addProvider(newBouncyCastleProvider());
BigIntegerb1 = new BigInteger(modulus);
BigInteger b2 = new BigInteger(exponent);
KeyFactorykeyFactory = KeyFactory.getInstance("RSA",
newBouncyCastleProvider());
RSAPrivateKeySpeckeySpec = new RSAPrivateKeySpec(b1, b2);
return(RSAPrivateKey) keyFactory.generatePrivate(keySpec);
}catch (Exception e) {
e.printStackTrace();
returnnull;
}
}
/**
* 公钥加密
*
* @param data
* @param publicKey
* @return
* @throws Exception
*/
publicstatic String encryptByPublicKey(String data, RSAPublicKey publicKey)
throwsException {
Security.addProvider(newBouncyCastleProvider());
Ciphercipher = Cipher.getInstance("RSA", new BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
//模长
intkey_len = publicKey.getModulus().bitLength() / 8;
// 加密数据长度 <= 模长-11
String[]datas = splitString(data, key_len - 11);
Stringmi = "";
//如果明文长度大于模长-11则要分组加密
for(String s : datas) {
mi+= bcd2Str(cipher.doFinal(s.getBytes()));
}
returnmi;
}
/**
* 私钥解密
*
* @param data
* @param privateKey
* @return
* @throws Exception
*/
publicstatic String decryptByPrivateKey(String data,
RSAPrivateKeyprivateKey) throws Exception {
Security.addProvider(newBouncyCastleProvider());
Ciphercipher = Cipher.getInstance("RSA", new BouncyCastleProvider());
cipher.init(Cipher.DECRYPT_MODE,privateKey);
//模长
intkey_len = privateKey.getModulus().bitLength() / 8;
byte[]bytes = data.getBytes();
byte[]bcd = ASCII_To_BCD(bytes, bytes.length);
//System.err.println(bcd.length);
//如果密文长度大于模长则要分组解密
Stringming = "";
byte[][]arrays = splitArray(bcd, key_len);
try{
for(byte[] arr : arrays) {
ming+= new String(cipher.doFinal(arr));
}
}catch (Exception e) {
e.printStackTrace();
}
returnming;
}
/**
* ASCII码转BCD码
*
*/
publicstatic byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
byte[]bcd = new byte[asc_len / 2];
intj = 0;
for(int i = 0; i < (asc_len + 1) / 2; i++) {
bcd[i]= asc_to_bcd(ascii[j++]);
bcd[i]= (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i]<< 4));
}
returnbcd;
}
publicstatic byte asc_to_bcd(byte asc) {
bytebcd;
if((asc >= "0") && (asc <= "9"))
bcd= (byte) (asc - "0");
elseif ((asc >= "A") && (asc <= "F"))
bcd= (byte) (asc - "A" + 10);
elseif ((asc >= "a") && (asc <= "f"))
bcd= (byte) (asc - "a" + 10);
else
bcd= (byte) (asc - 48);
returnbcd;
}
/**
* BCD转字符串
*/
publicstatic String bcd2Str(byte[] bytes) {
chartemp[] = new char[bytes.length * 2], val;
for(int i = 0; i < bytes.length; i++) {
val= (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
temp[i* 2] = (char) (val > 9 ? val + "A" - 10 : val + "0");
val= (char) (bytes[i] & 0x0f);
temp[i* 2 + 1] = (char) (val > 9 ? val + "A" - 10 : val + "0");
}
returnnew String(temp);
}
/**
* 拆分字符串
*/
publicstatic String[] splitString(String string, int len) {
intx = string.length() / len;
inty = string.length() % len;
intz = 0;
if(y != 0) {
z= 1;
}
String[]strings = new String[x + z];
Stringstr = "";
for(int i = 0; i < x + z; i++) {
if(i == x + z - 1 && y != 0) {
str= string.substring(i * len, i * len + y);
}else {
str= string.substring(i * len, i * len + len);
}
strings[i] = str;
}
returnstrings;
}
/**
* 拆分数组
*/
publicstatic byte[][] splitArray(byte[] data, int len) {
intx = data.length / len;
inty = data.length % len;
intz = 0;
if(y != 0) {
z= 1;
}
byte[][]arrays = new byte[x + z][];
byte[]arr;
for(int i = 0; i < x + z; i++) {
arr= new byte[len];
if(i == x + z - 1 && y != 0) {
System.arraycopy(data,i * len, arr, 0, y);
}else {
System.arraycopy(data,i * len, arr, 0, len);
}
arrays[i]= arr;
}
returnarrays;
}
}
需要引入jar
<scripttype="text/javascript" src="<%=basePath%>js/jquery.min.js"></script>
<script type="text/javascript"src="<%=basePath%>js/BigInt.js"></script>
<script type="text/javascript"src="<%=basePath%>js/Barrett.js"></script>
<script type="text/javascript"src="<%=basePath%>js/RSA.js"></script>
var key =RSAUtils.getKeyPair(publicexp,privateexp,moudel);
axes = axes.split("").reverse().join("");
returnRSAUtils.encryptedString(key,data);