简而言之:
- CTR是在对称加密的基础上,对原文填充偏移解密后的输出结果和原文再异或 得到密文,一般结果用十六进制输出
- ECB是在对称加密的基础上,将原文分成若干个段,对每个段进行加密,每个段的输出结果 合起来就是最后的密文,最后的密文一般用 Base64 输出
在Android中的实现就是先导入:
implementation 'org.apache.shiro:shiro-core:1.2.2'
这个包最新的Android导入会出现 一样的类Load不了,我懒得解决,就换成低版本的包了。
这边CTR用的是PKS5Padding
填充,也就是你 原文的bytes不是8或者16的倍数,会自动帮你用pks5填充
而ECB是NoPadding
,也就是无填充,在加密之前,你必须保证原文是16的倍数,如果不是的话你可以用你和后台协商好的字符填充,就比如我这里的"\0"填充
/**
* AES CRT加密
* 填充为PKCS5
*
* @param content 要加密的内容
* @param key 加密文件的秘钥
* @param iv 加密的偏移量
* @return 输出Hex十六进制再次加密的结果
**/
public static String encryptCRT(byte[] content, String key, String iv) {
String encodeStr = "";
try {
//产生密钥
byte[] keyBytes = key.getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
//构建Cipher对象,需要传入一个字符串,格式必须为"algorithm/mode/padding"或者"algorithm/",意为"算法/加密模式/填充方式"
Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5Padding");
//初始化Cipher对象
byte[] ivBytes = iv.getBytes();
IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
//加密数据
byte[] resultBytes = cipher.doFinal(content);
//结果用Hex十六进制转码
encodeStr = new String(Hex.encode(resultBytes));
return encodeStr;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return encodeStr;
}
/**
* AES CTR 解密
* 填充为PKCS5
*
* @param encode 加密过后的文件
* @param iv 偏移量
* @param key 秘钥文件
*/
public static String decryptCRT(String encode, String iv, String key) {
String decoded = "";
try {
byte[] bytes = Hex.decode(encode);
IvParameterSpec ivSpec = new IvParameterSpec(
iv.getBytes());
Key keys = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keys, ivSpec);
byte[] ret = cipher.doFinal(bytes);
decoded = new String(ret);
return decoded.trim();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return decoded;
}
/**
* AES ECB加密
* 填充为 “\0” noPadding
*
* @param content 要加密的内容
* @param key 加密文件的秘钥
* @return 输出Base64的结果
**/
public static String encryptECB(byte[] content, String key) {
String encodeStr = "";
try {
byte[] keyBytes = key.getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
//加密数据
int length = content.length;
int add = 16 - length % 16;
if (add == 16) {
add = 0;
}
byte[] contentNew = new byte[length + add];
//用'\0'加密
for (int i = 0; i < length + add; i++) {
if (i < length) {
contentNew[i] = content[i];
} else {
contentNew[i] = '\0' ;
}
}
byte[] resultBytes = cipher.doFinal(contentNew);
//结果用Base64
encodeStr = new String(Base64Util.encode(resultBytes));
return encodeStr;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return encodeStr;
}
/**
* AES ECB解密
*
* @param encode 加密过后的文件
* @param key 秘钥文件
*/
public static String decryptECB(String encode, String key) {
String decoded = "";
byte[] decodeBase64 = Base64.decode(encode);
int length = decodeBase64.length;
int add = 16 - length % 16;
if (add == 16) {
add = 0;
}
byte[] decodeContentNew = new byte[length + add];
//填充'\0'
for (int i = 0; i < length + add; i++) {
if (i < length) {
decodeContentNew[i] = decodeBase64[i];
} else {
decodeContentNew[i] = '\0' ;
}
}
try {
Key keys = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, keys);
byte[] ret = cipher.doFinal(decodeContentNew);
decoded = new String(ret);
return decoded.trim();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return decoded;
}