客户端将参数加密后通过http方式调用接口,接口服务方在获取参数进行解密时发生这个错误
发现主要原因为:
原始加密参数值为:
例如:dkjgoeFGKJ+ERO7/999JLJkjk==
获取的加密参数值为:
dkjgoeFGKJ ERO7/999JLJkjk==
注意到是+位置获取后试空格了
解决方式:
我采用的是加密时将密文字符串进行一次替换:如:str.replaceAll("[+]", "@");
注意:替换的字符 ,必须是rsa加密后转成字符串时不会存在的字符,比如,你不能将+替换为a等,因为我的密文是大小写字母,数字,/,+,=组成的.
获取方在获取后再进行替换:str.replaceAll("@", "+");
如果大家有更好的方式,欢迎留言.
代码示例:
import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
@SuppressWarnings("restriction")
public abstract class RSACoder {
private static final String KEY_ALGORITHM = "RSA";
private static final int MAX_ENCRYPT_1024 = 117;
private static final int MAX_DECRYPT_1024 = 128;
// private static final int MAX_ENCRYPT_2048 = 245;
// private static final int MAX_DECRYPT_2048 = 256;
private static byte[] decryptBASE64(String src) {
BASE64Decoder decoder = new BASE64Decoder();
try {
return decoder.decodeBuffer(src);
} catch (Exception ex) {
return null;
}
}
/**
* 该base64方法会自动换行
* @param src
* @return
*/
private static String encryptBASE64(byte[] src) {
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(src);
}
/**
* 公钥分段加密
* @param data 源数据
* @param publicKey 公钥(BASE64编码)
* @param length 段长
* @return
* @throws Exception
*/
private static byte[] encryptByPublicKey(byte[] data, String publicKey,int length)
throws Exception {
byte[] keyBytes = decryptBASE64(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicK = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > length) {
cache = cipher.doFinal(data, offSet, length);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * length;
}
byte[] encryptData = out.toByteArray();
out.close();
return encryptData;
}
/** *//**
*
* 私钥解密
*
*
* @param encryptedData 已加密数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
private static byte[] decryptByPrivateKey(byte[] data, String privateKey,int length)
throws Exception {
byte[] keyBytes = decryptBASE64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > length) {
cache = cipher.doFinal(data, offSet, length);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * length;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/**
* 加密
* @param data
* @param publicKey
* @return
*/
public static String encryptByPublicKey(String data, String publicKey) {
return encryptBASE64(encryptByPublicKey(data.getBytes(), publicKey, MAX_ENCRYPT_1024)).replaceAll("[+]", "@");
}
/**
* 解密
* @param data
* @param publicKey
* @return
*/
public static String decryptByPrivateKey(String data, String privateKey) {
return new String(decryptByPrivateKey(decryptBASE64(data.replaceAll("@", "+")), privateKey, MAX_DECRYPT_1024));
}
}