AES有五種加密模式分别是CBC、ECB、CTR、OCF、CFB;
1.如果不選擇填充會預設采用 ECB 模式和 PKCS5Padding 填充進行處理
AES 是塊加密,塊的長度是16個位元組,如果原文不到16個位元組,則需要填充至16個位元組後再進行處理。
AES密文長度=(原文長度/16)*16+16;最終長度為N+1;是以一定要選擇NoPadding模式。
2. 随機數生成器
在Android加密算法中需要随機數時要使用SecureRandom來擷取随機數。
注意不要給SecureRandom設定種子。調用seeded constructor或者setSeed(byte[])是不安全的。 SecureRandom()預設使用的是dev/urandom作為種子産生器,這個種子是不可預測的。
開發者建議:
SecureRandom secureRandom = new SecureRandom();
byte[] key = new byte[16]; //随機秘鑰
secureRandom.nextBytes(key)
/**
* 生成随機key
*
* @return key
* @throws Exception generate error
*/
public static byte[] getRawKey() throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = null;
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.JELLY_BEAN) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
/**
* AES 加密原文16位元組對齊,不足補零
*
* @param raw 加密秘鑰
* @param source 被加密資料
* @return 密文
* @throws Exception
*/
public static byte[] encrypt(byte[] raw, byte[] source) throws Exception {
byte[] original;
if (raw.length != 16)
throw new IllegalArgumentException("key is not 16 bytes");
if (source.length % 16 != 0) {
original = new byte[(source.length / 16 + source.length % 16 == 0 ? 0 : 1) * 16];
System.arraycopy(source, 0, original, 0, source.length);
} else {
original = Arrays.copyOf(source, source.length);
}
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(original);
return encrypted;
}
/**
* AES機密密文,AES/ECB/NoPadding參數要和加密時一樣,NoPadding原文密文長度一緻。
*
* @param raw 秘鑰
* @param encrypted 密文
* @return 原文
* @throws Exception
*/
public static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
if (encrypted.length % 16 != 0)
return encrypted;
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
/**
* RC4 加密原文16位元組對齊,不足補零
*
* @param raw 秘鑰
* @param source 原文
* @return 密文
* @throws Exception
*/
public static byte[] rc4(byte[] raw, byte[] source) throws Exception {
byte[] original;
if (raw.length != 16)
throw new IllegalArgumentException("key is not 16 bytes");
if (source.length % 16 != 0) {
original = new byte[(source.length / 16 + source.length % 16 == 0 ? 0 : 1) * 16];
System.arraycopy(source, 0, original, 0, source.length);
} else {
original = Arrays.copyOf(source, source.length);
}
SecretKeySpec skeySpec = new SecretKeySpec(raw, "RC4");
Cipher cipher = Cipher.getInstance("RC4");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(original);
return encrypted;
}
/**
* 從大到小排序
*
* @param source
*/
public static void sortByDescending(int source[]) {
int swap = 0;
for (int position = 0; position < source.length; position++) {
for (int location = 0; location < source.length; location++) {
if (source[position] > source[location]) {
swap = source[position];
source[position] = source[location];
source[location] = swap;
}
}
}
}
/**
* 生成随機的length長的String。
*
* @param length 生成的字元長度。
* @return 生成的随機字元。
*/
public static String getRandomString(int length) {
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(62);
sb.append(str.charAt(number));
}
return sb.toString();
}