js使⽤rsa加密⼤数据块的java实现
⽹上很多资料讲rsa的js实现与java实现,当数据量较⼩时基本都没问题,但加密的数据块过⼤时js与java加密的结果始终不⼀样,究其原因问题还是出在java代码上。对于⼤数据块java端要分块加密(这部分⽹上也有很多资料提及但加密结果与js 加密的并不⼀样),这⾥说下我⾃⼰亲⾝实践的结果。对要加密的字符串按每62个字符做分割,对分割的每组数据分别加密然后⽤空格连接,这样加密的结果就和js端加密的结果⼀样了。
JAVA RSA加密⼯具类
/**
* @author Administrator
*
*/
public class RSAUtil
{
public static final String NOPADDING = "RSA/NONE/NoPadding";
public static final String PKCS1PADDING = "RSA/ECB/PKCS1Padding";
public static String encrypt(String e, String n, String s) throws Exception
{
return encrypt(e, n, s, PKCS1PADDING);
}
public static String encrypt(String e, String n, String s, String transformation) throws Exception
{
RSAPublicKey key = (RSAPublicKey) getPublicKey(n, e);
// return encryptByPublicKey(s, key);
Cipher cipher = Instance(transformation, new BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] result = cipher.Bytes());
vertToHexString(result);
}
public static PublicKey getPublicKey(String modulus, String publicExponent) throws NoSuchAlgorithmException, InvalidKeySpecException
{
BigInteger bigIntModulus = new BigInteger(modulus, 16);
BigInteger bigIntPrivateExponent = new BigInteger(publicExponent, 16);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent);
KeyFactory keyFactory = Instance("RSA", new BouncyCastleProvider());
PublicKey publicKey = atePublic(keySpec);
return publicKey;
}
java源代码加密/**
* * 加密 *
*
* @param key
* 加密的密钥 *
* @param data
* 待加密的明⽂数据 *
* @return 加密后的数据 *
* @throws Exception
*/
public static String encryptWithSize(String e, String n, String text) throws Exception
{
try
{
RSAPublicKey pk = (RSAPublicKey) getPublicKey(n, e);
byte[] data = Bytes();
Cipher cipher = Instance("RSA/NONE/NoPadding", new BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, pk);
int blockSize = BlockSize();// 获得加密块⼤⼩,如:加密前数据为128个byte,⽽key_size=1024
// 加密块⼤⼩为127
// 加密块⼤⼩为127
// byte,加密后为128个byte;因此共有2个加密块,第⼀个127
// byte第⼆个为1个byte
int outputSize = OutputSize(data.length);// 获得加密块加密后块⼤⼩
int leavedSize = data.length % blockSize;
int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;
byte[] raw = new byte[outputSize * blocksSize];
int i = 0;
while (data.length - i * blockSize > 0)
{
if (data.length - i * blockSize > blockSize)
cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);
else
cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);
// 这⾥⾯doUpdate⽅法不可⽤,查看源代码后发现每次doUpdate后并没有什么实际动作除了把 byte[]放到
// ByteArrayOutputStream中,⽽最后doFinal的时候才将所有的byte[]进⾏加密,可是到了此时加密块⼤⼩很可能已经超出了 // OutputSize所以只好⽤dofinal⽅法。
i++;
}
vertToHexString(raw);
}
catch (Exception exp)
{
throw new Message());
}
}
/**
* 公钥加密
*
* @param data
* @param publicKey
* @return
* @throws Exception
*/
public static String encryptByPublicKey(String data, RSAPublicKey publicKey) throws Exception
{
Cipher cipher = Instance("RSA/NONE/NoPadding", new BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 模长
int key_len = Modulus().bitLength() / 8;
// 加密数据长度 <= 模长-11
String[] datas = splitString(data, key_len - 11);
String mi = "";
// 如果明⽂长度⼤于模长-11则要分组加密
for (String s : datas)
{
mi += bcd2Str(cipher.Bytes()));
}
return mi;
}
/**
* 拆分字符串
*/
public 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[] 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;
}
/**
* BCD转字符串
*/
public 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);
}
}
对加密块的处理
/**
* 通过指定长度分割字符串
*
* @param str
* @param len
* @return
*/
private List<String> splitStr(String str, int len) {
List<String> list = new ArrayList<String>();
String value = str;
while (value.length() > len) {
String sub = value.substring(0, len);
list.add(sub);
value = value.substring(len);
}
list.add(value);
return list;
}
/**
* 分组加密数据
*
* @param strList
* @return
* @throws Exception
*/
private String encryParams(List<String> strList) throws Exception {
StringBuffer sb;
String result;
StringBuffer retStr = new StringBuffer();
for (int i = 0; i < strList.size(); i++) {
sb = new (i));
result = pt("10001", rsakey, sb.reverse().toString(), RSAUtil.NOPADDING); retStr.append(result).append(" ");
}
String().trim();
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论