AES 加密
AES 有多种模式可用:ECB、CBC、CFB、OFB、CTR,常见的有 ECB 模式和 CBC 模式。
安全性
AES的ECB模式是将整个明文分成若干段相同的小段,然后对每一小段进行加密。
这种模式是最简单的加密方式,因为每个明文块独立加密,不涉及块之间的依赖。
ECB模式的优点是加密和解密速度快,实现简单,但在安全性方面存在缺陷,因为它对每个块独立加密,相同的明文块会产生相同的密文块。
这意味着,如果密文中出现重复的密文块,攻击者可以识别出这些重复,并可能利用这一特性进行密码分析攻击。
加密向量
在CBC模式中,明文首先被分割成若干个固定大小的块,然后每个块在与前一个密文块进行异或运算后,再与密钥进行加密。
这种模式需要一个初始化向量(IV),因为第一个明文块需要与IV进行异或运算。
IV是随机的,因此即使对相同的明文进行加密,每次得到的密文也会不同。
CBC模式的加密过程不是并行的,速度较慢,但解密可以并行化。
此外,如果密文中某一位被修改,只会影响这个密文块所对应的明文块以及下一个明文块的对应位,提供了一定的安全性。
模式选择
ECB模式不够安全,要考虑安全,同时又要兼顾效率,一般使用ECB模式就够了。
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
/**
* 对称加密
*
* @author Mr.css 2016-11-30
* @version 1.0
*/
public class AES {
private AES() {
}
private static final String CIPHER_AES = "AES";
/**
* CBC 模式
* <p>
* 算法/工作模式/填充方式
*/
private static final String CIPHER_AES_CBC_PKCS5Padding = "AES/CBC/PKCS5Padding";
/**
* 加密向量
*
* @param iv 向量
* @return IvParameterSpec
*/
public static IvParameterSpec getIvParameterSpec(byte[] iv) {
return new IvParameterSpec(iv);
}
/**
* 生成随机密钥
* <p>
* 注意:密钥长度的单位是位,128 位的密钥,转换成字节数组,就是 16 字节。
*
* @param len 密钥长度(位),可以是 128, 192或 256 位。
* @return SecretKey
* @throws IllegalArgumentException -
*/
public static SecretKey randomSecretKey(int len) throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(CIPHER_AES);
keyGenerator.init(len, new SecureRandom());
return keyGenerator.generateKey();
}
/**
* 生成密钥
*
* @param key 密钥,长度限定 16、24、32
* @return SecretKey
* @throws IllegalArgumentException -
*/
public static SecretKey generateSecretKey(byte[] key) {
int len = key.length;
if (len != 16 && len != 24 && len != 32) {
throw new IllegalArgumentException("key size must be a multiple of 32");
}
return new SecretKeySpec(key, CIPHER_AES);
}
/**
* CBC 模式加密
*
* @param data 数据
* @param key 密钥
* @param iv 加密向量
* @return 加密后的字符串
* @throws GeneralSecurityException any exception
*/
public static byte[] encrypt(byte[] data, Key key, IvParameterSpec iv) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(CIPHER_AES_CBC_PKCS5Padding);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
return cipher.doFinal(data);
}
/**
* CBC 模式解密
*
* @param data 数据
* @param key 密钥
* @param iv 加密向量
* @return 加密后的字符串
* @throws GeneralSecurityException any exception
*/
public static byte[] decrypt(byte[] data, Key key, IvParameterSpec iv) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(CIPHER_AES_CBC_PKCS5Padding);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
return cipher.doFinal(data);
}
/**
* ECB 模式
* <p>
* 这种模式不安全,可能导致重放攻击,因此在实际应用中建议使用其他模式,如CBC。
* <p>
* 算法/工作模式/填充方式
*/
private static final String CIPHER_AES_ECB_PKCS5Padding = "AES/ECB/PKCS5Padding";
/**
* ECB 模式加密
*
* @param input 数据
* @param key 密钥
* @return 加密后的字符串
* @throws GeneralSecurityException any exception
* @deprecated 这种模式不安全,可能导致重放攻击,因此在实际应用中建议使用其他模式,如CBC。
*/
@Deprecated
public static byte[] encryptECB(byte[] input, Key key) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(CIPHER_AES_ECB_PKCS5Padding);
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(input);
}
/**
* ECB 模式解密
*
* @param input 数据
* @param key 密钥
* @return 加密后的字符串
* @throws GeneralSecurityException any exception implement GeneralSecurityException
* @deprecated 这种模式不安全,可能导致重放攻击,因此在实际应用中建议使用其他模式,如CBC。
*/
@Deprecated
public static byte[] decryptECB(byte[] input, Key key) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(CIPHER_AES_ECB_PKCS5Padding);
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(input);
}
}
疯狂的妞妞 :每一天,做什么都好,不要什么都不做!