一直用的MD5加密方式,最近服务器需要更换RSA加密方式,据悉是因为RSA更安全吧,查阅资料之后实现了。
第一步:
将服务给你的rsa公钥copy到assets文件下(加密只需要公钥,服务器端游对应的私钥来解密)
第二步:
String rsaName = AppUtils.rsaEncode(this, name);
//rsa加密
public static String rsaEncode(Context context, String source) {
String afterencrypt = "";
try {
// 从文件中得到公钥
InputStream inPublic = context.getResources().getAssets().open("xxxxxx.pem");
PublicKey publicKey = RSAUtils.loadPublicKey(inPublic);//方法如下
// 加密
byte[] encryptByte = RSAUtils.encryptData(source.getBytes(), publicKey);//方法如下
// 为了方便观察吧加密后的数据用base64加密转一下,要不然看起来是乱码,所以解密是也是要用Base64先转换
afterencrypt = Base64.encodeToString(encryptByte, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
afterencrypt = afterencrypt.replaceAll("\n", "");//转换出来的字符串带有换行符,替换掉就好了
return afterencrypt;
}
private static String RSA = "RSA";
/**
* 从文件中输入流中加载公钥
*
* @param in 公钥输入流
* @throws Exception 加载公钥时产生的异常
*/
public static PublicKey loadPublicKey(InputStream in) throws Exception {
try {
return loadPublicKey(readKey(in));
} catch (IOException e) {
throw new Exception("公钥数据流读取错误");
} catch (NullPointerException e) {
throw new Exception("公钥输入流为空");
}
}
/**
* 读取密钥信息
*
* @param in
* @return
* @throws IOException
*/
private static String readKey(InputStream in) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String readLine = null;
StringBuilder sb = new StringBuilder();
while ((readLine = br.readLine()) != null) {
if (readLine.charAt(0) == '-') {
continue;
} else {
sb.append(readLine);
sb.append('\r');
}
}
return sb.toString();
}
/**
* 从字符串中加载公钥
*
* @param publicKeyStr 公钥数据字符串
* @throws Exception 加载公钥时产生的异常
*/
public static PublicKey loadPublicKey(String publicKeyStr) throws Exception {
try {
byte[] buffer = Base64.decode(publicKeyStr,Base64.DEFAULT);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此算法");
} catch (InvalidKeySpecException e) {
throw new Exception("公钥非法");
} catch (NullPointerException e) {
throw new Exception("公钥数据为空");
}
}
/**
* 用公钥加密 <br>
* 每次加密的字节数,不能超过密钥的长度值减去11
*
* @param data 需加密数据的byte数据
* @param pubKey 公钥
* @return 加密后的byte型数据
*/
public static byte[] encryptData(byte[] data, PublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");//这里的参数一定要填这个,否则会导致加密后和服务器不一致
// 编码前设定编码方式及密钥
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 传入编码数据并返回编码结果
return cipher.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
P.S.遇到两个问题
1.Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");//这里的参数一定要填这个,否则会导致加密后和服务器不一致
开始这里的参数传递的是"RSA",导致加密后和服务器不一致,所以一定要填如上参数
2.afterencrypt = afterencrypt.replaceAll("\n", "");//转换出来的字符串带有换行符,替换掉就好了
转换出来字符串带有换行符,替换all就好了