AES加密解密使用同一个密钥(有key和iv两个值,这两个值可以写死,可以随机生成),所以称为对称加密 ....
RSA有公钥,私钥(公钥加密,私钥解密,私钥加密,公钥解密),所以称为非对称加密
- 简单说下结合两种加密方式的流程
- aes生成密钥对数据进行加密,rsa对aes的密钥进行公钥加密,然后将密文和加密的aes密钥上传给后台(统一在拦截器中处 理)
- 后台拿到密文和aes密钥后,用rsa私钥对aes密钥进行解密,将解密后的aes密钥对密文进行解密,得到明文数据。
- 后台用aes密钥对将要返回给客户端的数据进行加密,将密文传送给客户端
- 客户端用aes密钥对密文进行解密,得到明文数据(统一在json解析中处理)
下面是代码部分,需要用到另外三个文件 AES2.java AesEntity.kt RSAUtils.java
- AES2.java
import android.util.Log;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AES2 {
private final String CIPHERMODEPADDING = "AES/CBC/PKCS5Padding";// AES/CBC/PKCS7Padding
public String getIv() {
return getOrderIdByUUId();
}
public String getPwd() {
return getOrderIdByUUId();
}
public String encrypt(String pwd, String iv, byte[] plaintext) throws Exception {
SecretKeySpec mPwd = new SecretKeySpec(pwd.getBytes("UTF-8"), "CBC");
IvParameterSpec mIv = new IvParameterSpec(iv.getBytes());
byte[] cipherText = encrypt(CIPHERMODEPADDING, mPwd, mIv, plaintext);
String base64_ciphertext = Base64Encoder.encode(cipherText);
return base64_ciphertext;
}
public String decrypt(String pwd, String iv, String ciphertext_base64) throws Exception {
SecretKeySpec mPwd = new SecretKeySpec(pwd.getBytes("UTF-8"), "CBC");
IvParameterSpec mIv = new IvParameterSpec(iv.getBytes());
byte[] s = Base64Decoder.decodeToBytes(ciphertext_base64);
String decrypted = new String(decrypt(CIPHERMODEPADDING, mPwd, mIv, s));
return decrypted;
// byte[] s = Base64Decoder.decodeToBytes(ciphertext_base64);
// String decrypted = new String(decrypt(CIPHERMODEPADDING, mPwd, mIv, s));
// return decrypted;
}
/**
* 将二进制转换成16进制
*
* @param buf
* @return
*/
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
private byte[] encrypt(String cmp, SecretKey sk, IvParameterSpec IV,
byte[] msg) {
try {
Cipher c = Cipher.getInstance(cmp);
c.init(Cipher.ENCRYPT_MODE, sk, IV);
return c.doFinal(msg);
} catch (NoSuchAlgorithmException nsae) {
Log.e("AESdemo", "no cipher getinstance support for " + cmp);
} catch (NoSuchPaddingException nspe) {
Log.e("AESdemo", "no cipher getinstance support for padding " + cmp);
} catch (InvalidKeyException e) {
Log.e("AESdemo", "invalid key exception");
} catch (InvalidAlgorithmParameterException e) {
Log.e("AESdemo", "invalid algorithm parameter exception");
} catch (IllegalBlockSizeException e) {
Log.e("AESdemo", "illegal block size exception");
} catch (BadPaddingException e) {
Log.e("AESdemo", "bad padding exception");
}
return null;
}
private byte[] decrypt(String cmp, SecretKey sk, IvParameterSpec IV,
byte[] ciphertext) {
try {
Cipher c = Cipher.getInstance(cmp);
c.init(Cipher.DECRYPT_MODE, sk, IV);
return c.doFinal(ciphertext);
} catch (NoSuchAlgorithmException nsae) {
Log.e("AESdemo", "no cipher getinstance support for " + cmp);
} catch (NoSuchPaddingException nspe) {
Log.e("AESdemo", "no cipher getinstance support for padding " + cmp);
} catch (InvalidKeyException e) {
Log.e("AESdemo", "invalid key exception");
} catch (InvalidAlgorithmParameterException e) {
Log.e("AESdemo", "invalid algorithm parameter exception");
} catch (IllegalBlockSizeException e) {
Log.e("AESdemo", "illegal block size exception");
} catch (BadPaddingException e) {
Log.e("AESdemo", "bad padding exception");
e.printStackTrace();
}
return null;
}
//获取随机16位数
public static String getOrderIdByUUId() {
int machineId = 1;//最大支持1-9个集群机器部署
int hashCodeV = UUID.randomUUID().toString().hashCode();
if (hashCodeV < 0) {//有可能是负数
hashCodeV = -hashCodeV;
}
// 0 代表前面补充0
// 4 代表长度为4
// d 代表参数为正数型
return machineId + String.format("%015d", hashCodeV);
}
private byte[] addPadding(byte[] plain) {
byte plainpad[] = null;
int shortage = 16 - (plain.length % 16);
if (shortage == 0)
shortage = 16;
plainpad = new byte[plain.length + shortage];