AES加密
首先得说的是让我困扰的参数问题,只有这个问题搞明白了才能有然后.
示例
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
首先应该明白AES是基于数据块的加密方式,也就是说,每次处理的数据是一块(16字节),
当数据不是16字节的倍数时填充,这就是所谓的分组密码(区别于基于比特位的流密码),16字节是分组长度。
ECB和CBC的加密结果是不一样的,两者的模式不同,而且CBC会在第一个密码块运算时加入一个初始化偏移量
分组加密的几种方式
- ECB(Electronic Code Book,电子密码本):是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。
- CBC(Cipher Block Chaining,加密块链):是一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解难度。
- CFB(Cipher FeedBack Mode,加密反馈)/OFB(Output FeedBack,输出反馈)实际上是一种反馈模式,目的也是增强破解的难度。
如果不指定算法模式,会默认使用ECB算法,而且完全忽略IV(偏移值/向量)参数,
如果忽略padding(补码/填充)方式,程序默认为PKCS5Padding
;
Cipher c = Cipher.getInstance("AES");
SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes("UTF-8"), "AES");
c.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(IV));
如果使用了ECB算法模式,偏移量是不会起作用的,偏移量默认为:1234567890123456。
AES定义了密钥为128bit和256bit两个Rijndael算法版本。
在java中定义一个String
类型密钥KEY.getBytes("UTF-8")
,返回的就是128bit。
32 hex char = 16byte = 128bit
两者只能使用一种。
加密:
java
private static String key="144831ab75bf78c6";
private static String algorithm = "AES/ECB/PKCS7Padding";
public static String enCrypt(String text){
try {
Cipher c = Cipher.getInstance(algorithm);
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
c.init(Cipher.ENCRYPT_MODE,keySpec);
return Base64.encodeToString(c.doFinal(text.getBytes("UTF-8")),Base64.DEFAULT);
} catch (Exception e){
e.printStackTrace();
}
return null;
}
c#
public static byte[] AESEncrypt(string plainText, string strKey)
{
SymmetricAlgorithm des = Rijndael.Create();
byte[] inputByteArray = Encoding.UTF8.GetBytes(plainText);
des.Key = Encoding.UTF8.GetBytes(strKey);
des.Mode = CipherMode.ECB;
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
byte[] cipherBytes = ms.ToArray();
cs.Close();
ms.Close();
return cipherBytes;
}
解密
java
public static String decypt(String key,String text){
byte[] data=Base64.decode(text, Base64.DEFAULT);
try {
Cipher c = Cipher.getInstance(algorithm);
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
c.init(Cipher.DECRYPT_MODE,keySpec);
byte[] original = c.doFinal(data);
return new String(original, "UTF-8");
} catch (Exception e){
e.printStackTrace();
}
return null;
}
反向思路是一样的。
参考文档Google API、Oracle API。