由于很多因素使得客户端和服务器之间交互的一些数据都要经过加密,为了方便,很多使用非对称的加密算法进行加密,其中RSA算法成为首选。下面说说在Android客户端怎中怎么应用这种加密方案。
首先在我们Android客户端启动应用程序的时候,我们先请求一个服务器,让服务将RSA的公钥返回给我们,然后我们将取得的公钥对我们的数据进行加密,然后再返回给服务器,服务器将用私钥解密即可。
一般为了方便,服务器传递公钥的时候,不直接将公钥传递过来,我们都知道RSA算法是通过对大素数的一些操作而得来的,这时候我们主要得到两个数就可以重新生成一个公钥了。要生成一个公钥,必须要知道modulus和exponent,所以服务器一开始只要返回这两个数据就OK。
下面方法是通过modulus和exponent生成公钥的:
/**
* 描述:根据所提供的公钥系数和公钥指数,重新构建RSA公钥
*
* @param modulus
* 公钥系数
* @param publicExponent
* 公钥指数
* @return RSAPublicKey
* */
private RSAPublicKey rebuildRSAPublicKey(String modulus, String publicExponent) {
RSAPublicKey rpk = null;
KeyFactory kf = null;
try {
kf = KeyFactory.getInstance("RSA");
rpk = (RSAPublicKey) kf.generatePublic(new RSAPublicKeySpec(new BigInteger(modulus, 16), new BigInteger(
publicExponent, 16)));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return rpk;
}
有了公钥,那就好办了,我们由公钥初始化一个加密工具了。
当然,服务器也可以直接将公钥传递过来,然后客户端再重新生成公钥,做法如下:
现将公钥转码(这里设定服务器语言为java):
byte[] keys = publicKey.getEncoded();
String string = bytesToHexString(keys);
其中bytesToHexString()这个方法是将byte[]转换成十六进制的字符串,方便将其放在json里面然后传递给客户端
其实现如下:
public String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
客户端通过解析json字段,获取其内容,然后进行下面操作,重新还原成公钥:其中hexStringToBytes()方法是将字符串转换成byte[]数组,记得与上面的要对应,实现如下:
private PublicKey buildPublicKey(String keyString) throws Exception {
byte[] keys = hexStringToBytes(keyString);
KeySpec keySpec = new X509EncodedKeySpec(keys);
KeyFactory factory = KeyFactory.getInstance("RSA");
return factory.generatePublic(keySpec);
}
public byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
/**
* Convert char to byte
*
* @param c
* char
* @return byte
*/
private byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}