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);
    }
}

posted on 2018-05-24 00:08  疯狂的妞妞  阅读(194)  评论(0编辑  收藏  举报

导航