我在使用RSAPrivateKey 和RSAPublicKey加密解密的的功能如下:
1、使用RSAPrivateKey 加密数据,然后使用RSAPublicKey解密数据;
2、使用RSAPublicKey加密数据,然后使用RSAPrivateKey 解密数据;
实际操作中能够实现该逻辑,但是发现我的代码在加密解密的过程中中,加密时有117bute的限制;解密事由128byte的限制。
代码如下:
package cn.fengLone.pay.util;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.crypto.Cipher;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* RSA私钥公钥字符串、对象生成工具
*
* 本工具类提供以下几种方法:
*
* 1、生成基于PublicKey 和PrivateKey对象的方法 initRSAKeys()
* 2、将PrivateKey对象转为私钥字符串
* 3、将PublicKey对象转为公钥字符串
* 4、将私钥字符串转为PrivateKey对象
* 5、将公钥字符串转为PublicKey对象
* 6、将公钥和私钥以文件形式保存
* 7、公钥加密、私钥解密
* 8、私钥加密、公钥解密
*
* @author Guo pengFei
*
* @date 2017-7-27
*
* @version V1.0
*
* @compeny 深证风轮科技有限公司
*
* @site https://www.blog-china.cn
*
*/
public class RSAUtils {
/** 指定加密算法为RSA */
private static final String ALGORITHM = "RSA";
/** 指定公钥存放文件 */
private static String PUBLIC_KEY_FILE = "D://key/PublicKey.txt";
/** 指定私钥存放文件 */
private static String PRIVATE_KEY_FILE = "D://key/PrivateKey.txt";
/**
* 以文件形式生成公钥和私钥,并保存
*
* @return
* @throws Exception
*/
public static boolean writeKeyFile() throws Exception {
Map<String, Object> map = initRSAKeys();
Key publicKey = (Key) map.get("pubKey");
Key privateKey = (Key) map.get("priKey");
String pubKeyString = RSAUtils.getKeyString(publicKey);
String priKeyString = RSAUtils.getKeyString(privateKey);
System.out.println(pubKeyString);
System.out.println();
System.out.println(priKeyString);
/** 用对象流将生成的密钥写入文件 */
FileOutputStream oos1 = new FileOutputStream(PUBLIC_KEY_FILE);
oos1.write(pubKeyString.getBytes("UTF-8")); // 可以指定编码
FileOutputStream oos2 = new FileOutputStream(PRIVATE_KEY_FILE);
oos2.write(priKeyString.getBytes("UTF-8")); // 可以指定编码
/** 清空缓存,关闭文件输出流 */
if (oos1 != null) {
oos1.close();
}
if (oos2 != null) {
oos2.close();
}
return true;
}
/**
* 生产RSA的私钥和公钥
*
* @return
* @throws NoSuchAlgorithmException
*/
public static Map<String, Object> initRSAKeys()
throws NoSuchAlgorithmException {
// TODO Auto-generated method stub
Map<String, Object> map = getKeys();
// 生成公钥和私钥
RSAPublicKey publicKey = (RSAPublicKey) map.get("public");
RSAPrivateKey privateKey = (RSAPrivateKey) map.get("private");
// 模
String modulus = publicKey.getModulus().toString();
// 公钥指数
String public_exponent = publicKey.getPublicExponent().toString();
// 私钥指数
String private_exponent = privateKey.getPrivateExponent().toString();
// 使用模和指数生成公钥和私钥
RSAPublicKey pubKey = RSAUtils.getPublicKey(modulus, public_exponent);
RSAPrivateKey priKey = RSAUtils
.getPrivateKey(modulus, private_exponent);
map.put("pubKey", pubKey);
map.put("priKey", priKey);
return map;
}
/**
* 把公钥字符串转为对象
*
* @param key
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* 把私钥字符串转为对象
*
* @param key
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
/**
* 得到密钥字符串(经过base64编码)
*
* @return
*/
public static String getKeyString(Key key) throws Exception {
byte[] keyBytes = key.getEncoded();
String s = (new BASE64Encoder()).encode(keyBytes);
return s;
}
/**
* 生成公钥和私钥
*
* @throws NoSuchAlgorithmException
*
*/
private static HashMap<String, Object> getKeys()
throws NoSuchAlgorithmException {
HashMap<String, Object> map = new HashMap<String, Object>();
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
map.put("public", publicKey);
map.put("private", privateKey);
return map;
}
/**
* 使用模和指数生成RSA公钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
* @param modulus
* 模
* @param exponent
* 指数
* @return
*/
private static RSAPublicKey getPublicKey(String modulus, String exponent) {
try {
BigInteger b1 = new BigInteger(modulus);
BigInteger b2 = new BigInteger(exponent);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 使用模和指数生成RSA私钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
* @param modulus
* 模
* @param exponent
* 指数
* @return
*/
private static RSAPrivateKey getPrivateKey(String modulus, String exponent) {
try {
BigInteger b1 = new BigInteger(modulus);
BigInteger b2 = new BigInteger(exponent);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 公钥加密
*
* @param data
* @param publicKey
* @return
* @throws Exception
*/
public static String encryptByPublicKey(Map<String, String> data, RSAPublicKey publicKey)
throws Exception {
if(data == null)
return null;
StringBuffer buffer = new StringBuffer();
buffer.append("{");
Iterator<String> iterator = data.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
String value = data.get(key);
buffer.append("'").append(key).append("':'").append(value).append("',");
}
String result = buffer.substring(0,buffer.length()-1)+"}";
System.out.println(result);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 模长
int key_len = publicKey.getModulus().bitLength() / 8;
// 加密数据长度 <= 模长-11
String[] datas = splitString(result, key_len - 11);
String mi = "";
// 如果明文长度大于模长-11则要分组加密
for (String s : datas) {
mi += bcd2Str(cipher.doFinal(s.getBytes()));
}
return mi;
}
/**
* 公钥加密
*
* @param data
* @param publicKey
* @return
* @throws Exception
*/
public static String encryptByPublicKey(String data, RSAPublicKey publicKey)
throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 模长
int key_len = publicKey.getModulus().bitLength() / 8;
// 加密数据长度 <= 模长-11
String[] datas = splitString(data, key_len - 11);
String mi = "";
// 如果明文长度大于模长-11则要分组加密
for (String s : datas) {
mi += bcd2Str(cipher.doFinal(s.getBytes()));
}
return mi;
}
/**
* 私钥加密过程
*
* @param privateKey
* 私钥
* @param plainTextData
* 明文数据
* @return
* @throws Exception
* 加密过程中的异常信息
*/
public static String encryptByPrivateKey1(RSAPrivateKey privateKey,
String data) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
// 模长
int key_len = privateKey.getModulus().bitLength() / 8;
// 加密数据长度 <= 模长-11
String[] datas = splitString(data, key_len - 11);
String mi = "";
// 如果明文长度大于模长-11则要分组加密
for (String s : datas) {
mi += bcd2Str(cipher.doFinal(s.getBytes()));
}
return mi;
}
/**
* 公钥解密过程
*
* @param publicKey
* 公钥
* @param cipherData
* 密文数据
* @return 明文
* @throws Exception
* 解密过程中的异常信息
*/
public static String decryptByPublicKey(RSAPublicKey publicKey, String data)
throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, publicKey);
// 模长
int key_len = publicKey.getModulus().bitLength() / 8;
byte[] bytes = data.getBytes();
byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
System.err.println(bcd.length);
// 如果密文长度大于模长则要分组解密
String ming = "";
byte[][] arrays = splitArray(bcd, key_len);
for (byte[] arr : arrays) {
ming += new String(cipher.doFinal(arr));
}
return ming;
}
/**
* 私钥解密
*
* @param data
* @param privateKey
* @return
* @throws Exception
*/
public static String decryptByPrivateKey(String data,
RSAPrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
// 模长
int key_len = privateKey.getModulus().bitLength() / 8;
byte[] bytes = data.getBytes();
byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
System.err.println(bcd.length);
// 如果密文长度大于模长则要分组解密
String ming = "";
byte[][] arrays = splitArray(bcd, key_len);
for (byte[] arr : arrays) {
ming += new String(cipher.doFinal(arr));
}
return ming;
}
/**
* ASCII码转BCD码
*
*/
private static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
byte[] bcd = new byte[asc_len / 2];
int j = 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));
}
return bcd;
}
private static byte asc_to_bcd(byte asc) {
byte bcd;
if ((asc >= '0') && (asc <= '9'))
bcd = (byte) (asc - '0');
else if ((asc >= 'A') && (asc <= 'F'))
bcd = (byte) (asc - 'A' + 10);
else if ((asc >= 'a') && (asc <= 'f'))
bcd = (byte) (asc - 'a' + 10);
else
bcd = (byte) (asc - 48);
return bcd;
}
/**
* BCD转字符串
*/
private static String bcd2Str(byte[] bytes) {
char temp[] = 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');
}
return new String(temp);
}
/**
* 拆分字符串
*/
private static String[] splitString(String string, int len) {
int x = string.length() / len;
int y = string.length() % len;
int z = 0;
if (y != 0) {
z = 1;
}
String[] strings = new String[x + z];
String str = "";
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;
}
return strings;
}
/**
* 拆分数组
*/
private static byte[][] splitArray(byte[] data, int len) {
int x = data.length / len;
int y = data.length % len;
int z = 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;
}
return arrays;
}
}
其中,我使用encryptByPrivateKey1()方法进行加密,使用decryptByPublicKey()方法进行解密;
调用方法示例如下:
static void testEn() {
String tempVale = "{'order_id':'20171020172857','total_pay':'301','client_ip':'10.12.123.23','order_name':'测试商品','order_id':'20171020172857','pay_type':'003'}";
String privateKey = "MIIBNgIBADANBgkqhkiG9w0BAQEFAASCASAwggEcAgEAAoGBAIEYqSVG3maZt1l4dvbQSQFwiGuT4jaA8DR8/4s1Fi18pvP395Z8y9GSyIoPWoQN/XcHT/nHkeSsz6O2ohSVDugf4C/UfWVZQInOYcs1rXsVvTLchai/amEOZXKz8D27kIok9omIRm3d0Sa1Vlrr3N7e4Bhmp7dWXl5LI/cGzMELAgEAAoGAP18GsSjPxdfRXFc5NsFaBR3jqcNneU/kGi/+FazSnTOilQJ1hGbweokubi9JRKfFc6egR8ICyRlXuErP14CwVuK9HWyDckCZNjBn/5mzaYJgqZL7Fzg/kDm28s2csWAiASzEW+Kmzp9QKNsHM4VqAzJsAYgjQBZYQTZiWb3KDCECAQACAQACAQACAQACAQA==";
try {
RSAPrivateKey pri = (RSAPrivateKey) RSAUtils
.getPrivateKey(privateKey);
String sign_value = RSAUtils.encryptByPrivateKey1(pri, tempVale);
System.out.println("respPost==" + sign_value);
RSAPublicKey pub = (RSAPublicKey) RSAUtils
.getPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBGKklRt5mmbdZeHb20EkBcIhrk+I2gPA0fP+LNRYtfKbz9/eWfMvRksiKD1qEDf13B0/5x5HkrM+jtqIUlQ7oH+Av1H1lWUCJzmHLNa17Fb0y3IWov2phDmVys/A9u5CKJPaJiEZt3dEmtVZa69ze3uAYZqe3Vl5eSyP3BszBCwIDAQAB");
String ming = RSAUtils.decryptByPublicKey(pub, sign_value);
System.out.println(ming);
} catch (Exception e) {
e.printStackTrace();
}
}
但是我查阅了很多资料,不知道分组加密和解密的代码逻辑该怎么写,有大神们解决下吗?
谢谢!
如楼上所说,RSA加密是有长度限制的.单纯用RSA加密较长数据时得使用分段加密,效率低下.用RSA+AES是比较主流的做法:AES加密数据产生密文,RSA加密AES密钥产生加密后的AES密钥,然后将密文和加密后的AES密钥一起传输
RSA 加密长字符串,效率不高,实践中,很少用RSA加密长字符串。
常见的办法是RSA交换密码, 用密码做AES对称加密。
楼主您好,所有非对称加密,密钥长度直接影响可以加密的内容长度,如果你现在用的是RSA128位加密,可以试试做RSA的256位加密
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。