Back to Posts

AES加密

Posted in Android

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 APIOracle API

Android Devoloper. This is my personal blog and any views expressed here are mine.