AES加解密算法之CBC,ECB模式(亲测可用)

找了好多工具类, 下面这个亲测可用, 直接考成工具类使用
可在解密网站解析: https://www.ssleye.com/aes_cipher.html
在这里插入图片描述
代码如下:

/**
 * AES加密解密字符串工具类
 * 概述:AES高级加密标准,是对称密钥加密中最流行的算法之一;
 * 工作模式包括:ECB、CBC、CTR、OFB、CFB;
 * 使用范围:该工具类仅支持CBC模式下的:
 * 数据块:128位
 * 密码(key):32字节长度(例如:12345678901234567890123456789012)
 * 偏移量(iv):16字节长度(例如:1234567890123456)
 * 字符集:UTF-8
 */

public class AesUtil {
    //偏移量
    public static final String VIPARA = "1234123412341234";   //AES 为16bytes. DES 为8bytes

    //编码方式
    public static final String CODE_TYPE = "UTF-8";
//    public static final String CODE_TYPE = "GBK";

    //填充类型(四选一,看你选择CBC还是ECB)
      public static final String AES_TYPE = "AES/CBC/PKCS5Padding";
    //public static final String AES_TYPE = "AES/ECB/PKCS7Padding";
    //此类型 加密内容,密钥必须为16字节的倍数位,否则抛异常,需要字节补全再进行加密
    //public static final String AES_TYPE = "AES/ECB/NoPadding";
    //java 不支持ZeroPadding
    //public static final String AES_TYPE = "AES/CBC/ZeroPadding";

    //私钥
    private static final String AES_KEY = "1234123412341234";   //AES固定格式为128/192/256 bits.即:16/24/32bytes。DES固定格式为128bits,即8bytes。

    //字符补全
    private static final String[] consult = new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G"};


    /**
     * 加密
     *
     * @param cleartext
     * @return
     */
    public static String encrypt(String cleartext) {
        //加密方式: AES128(CBC/PKCS5Padding) + Base64, 私钥:1111222233334444
        try {
            IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
            //两个参数,第一个为私钥字节数组, 第二个为加密方式 AES或者DES
            SecretKeySpec key = new SecretKeySpec(AES_KEY.getBytes(), "AES");
            //实例化加密类,参数为加密方式,要写全
            Cipher cipher = Cipher.getInstance(AES_TYPE); //PKCS5Padding比PKCS7Padding效率高,PKCS7Padding可支持IOS加解密
            //初始化,此方法可以采用三种方式,按加密算法要求来添加。(1)无第三个参数(2)第三个参数为SecureRandom random = new SecureRandom();中random对象,随机数。(AES不可采用这种方法)(3)采用此代码中的IVParameterSpec
            //加密时使用:ENCRYPT_MODE;  解密时使用:DECRYPT_MODE;
            cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv); //CBC类型的可以在第三个参数传递偏移量zeroIv,ECB没有偏移量
            //加密操作,返回加密后的字节数组,然后需要编码。主要编解码方式有Base64, HEX, UUE,7bit等等。此处看服务器需要什么编码方式
            byte[] encryptedData = cipher.doFinal(cleartext.getBytes(CODE_TYPE));

            return new BASE64Encoder().encode(encryptedData);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 解密
     *
     * @param encrypted
     * @return
     */
    public static String decrypt(String encrypted) {
        try {
            byte[] byteMi = new BASE64Decoder().decodeBuffer(encrypted);
            IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
            SecretKeySpec key = new SecretKeySpec(
                    AES_KEY.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance(AES_TYPE);
            //与加密时不同MODE:Cipher.DECRYPT_MODE
            cipher.init(Cipher.DECRYPT_MODE, key, zeroIv);  //CBC类型的可以在第三个参数传递偏移量zeroIv,ECB没有偏移量
            byte[] decryptedData = cipher.doFinal(byteMi);
            return new String(decryptedData, CODE_TYPE);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 测试,这里是对对象加密, 
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        List<UserDetailInfoDTO> list = new ArrayList<>();
        UserDetailInfoDTO userDetailInfoDTO = new UserDetailInfoDTO();
        userDetailInfoDTO.setUserId("1111");
        userDetailInfoDTO.setDistinctId("4444444");
        list.add(userDetailInfoDTO);
        String string = JSON.toJSONString(list);
        test(string);
    }

    public static void test(String content) throws UnsupportedEncodingException {
        System.out.println("加密内容:" + content);
        //字节数
        int num = content.getBytes(CODE_TYPE).length;
        System.out.println("加密内容字节数: " + num);
        System.out.println("加密内容是否16倍数: " + (num % 16 == 0 ? true : false));

        //字节补全
        if (AES_TYPE.equals("AES/ECB/NoPadding")) {
            System.out.println();
            content = completionCodeFor16Bytes(content);
            System.out.println("加密内容补全后: " + content);
        }

        System.out.println();

        // 加密
        String encryptResult = encrypt(content);
        content = new String(encryptResult);
        System.out.println("加密后:" + content);

        System.out.println();

        // 解密
        String decryptResult = decrypt(encryptResult);
        content = new String(decryptResult);
        //还原
        if (AES_TYPE.equals("AES/ECB/NoPadding")) {
            System.out.println("解密内容还原前: " + content);
            content = resumeCodeOf16Bytes(content);
        }

        System.out.println("解密完成后:" + content);
    }


    //NoPadding
    //补全字符
    public static String completionCodeFor16Bytes(String str) throws UnsupportedEncodingException {
        int num = str.getBytes(CODE_TYPE).length;
        int index = num % 16;
        //进行加密内容补全操作, 加密内容应该为 16字节的倍数, 当不足16*n字节是进行补全, 差一位时 补全16+1位
        //补全字符 以 $ 开始,$后一位代表$后补全字符位数,之后全部以0进行补全;
        if (index != 0) {
            StringBuffer sbBuffer = new StringBuffer(str);
            if (16 - index == 1) {
                sbBuffer.append("$" + consult[16 - 1] + addStr(16 - 1 - 1));
            } else {
                sbBuffer.append("$" + consult[16 - index - 1] + addStr(16 - index - 1 - 1));
            }
            str = sbBuffer.toString();
        }
        return str;
    }

    //追加字符
    public static String addStr(int num) {
        StringBuffer sbBuffer = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            sbBuffer.append("0");
        }
        return sbBuffer.toString();
    }


    //还原字符(进行字符判断)
    public static String resumeCodeOf16Bytes(String str) {
        int indexOf = str.lastIndexOf("$");
//    	System.out.println(indexOf);
        if (indexOf == -1) {
            return str;
        }
        String trim = str.substring(indexOf + 1, indexOf + 2).trim();
//    	System.out.println(trim);
        int num = 0;
        for (int i = 0; i < consult.length; i++) {
            if (trim.equals(consult[i])) {
                num = i;
            }
        }
        if (num == 0) {
            return str;
        }
        return str.substring(0, indexOf).trim();
    }

}

公众号搜索: 意姆斯Talk, 即可领取大量学习资料及实战经验
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: C语言中的AES算法可以使用ECB模式CBC模式进行加密和解密操作。 ECB(Electronic Codebook)模式是最简单的AES加密模式之一。它将明文分成一个个固定长度的块,然后使用AES算法对每个块进行单独的加密。每个块之间没有依赖关系,因此可以并行进行处理。ECB模式的弱点是同样的明文块会被加密成相同的密文块,容易受到密码分析攻击,因此不推荐在安全性要求高的场景中使用。 CBC(Cipher Block Chaining)模式是常用的AES加密模式之一。它在加密每个分组前,会使用前一个分组的密文与当前分组的明文进行异或运算。这样做的目的是为了生成更大的随机性,使得每个分组的密文都受到了前面所有分组的影响。在解密过程中,需要使用前一个分组的密文与当前分组的密文进行异或运算,才能得到正确的明文。CBC模式相比于ECB模式,对于相同的明文块会加密成不同的密文块,提高了安全性。同时,由于每个分组的加密都依赖于前一个分组的密文,所以CBC模式不能进行并行加密和解密。 在C语言中,可以使用OpenSSL等库来实现AES算法ECBCBC模式。通过调用相应的函数,传入明文、密钥和向量等参数,就可以完成加密和解密操作。需要注意的是,CBC模式需要注意向量的选择,确保向量的唯一性,否则可能会导致安全性问题。 总之,ECBCBC是常用的AES加密算法模式ECB模式简单快速,但安全性较差;CBC模式安全性较好,但加解密顺序有要求,不能并行处理。具体选择哪种模式,需要根据实际的需求和安全性要求来决定。 ### 回答2: C语言中的AES加密算法是一种对称加密算法,可以使用ECB(Electronic Codebook)和CBC(Cipher Block Chaining)模式进行加解密ECB模式对明文进行分块加密,每一块的长度等于AES的分组长度,一般为128位(16字节)。每一块明文独立地被加密,然后将加密结果合并成密文。ECB模式简单直观,但由于每一块明文被独立加密,相同的明文块会生成相同的密文块。因此,ECB模式容易受到密码分析的攻击,不适合加密长度大于一个分组长度的数据。 CBC模式通过引入初始化向量(IV)和前一个密文块与当前明文块的异或操作,提供了更好的安全性。首先,将IV与第一个明文块异或,然后将结果与密钥进行加密得到第一个密文块。之后,将第一个密文块与第二个明文块异或,再加密得到第二个密文块。以此类推,直到所有明文块都被处理成密文块。在CBC模式下,一个明文块的变化会影响后续所有密文块的产生,增加了密码分析的难度。 在C语言中使用AES算法ECBCBC模式,可以通过调用相应的加密库函数来实现。对于ECB模式,可以使用函数如下: ```c #include <openssl/aes.h> AES_KEY key; AES_set_encrypt_key(userKey, KEY_LENGTH, &key); AES_encrypt(inputBlock, outputBlock, &key); ``` 对于CBC模式,需要使用IV和相应的解密函数。加密和解密的过程如下: ```c #include <openssl/aes.h> AES_KEY key; unsigned char iv[KEY_LENGTH]; // 初始化IV memset(iv, 0x00, sizeof(iv)); AES_set_encrypt_key(userKey, KEY_LENGTH, &key); AES_cbc_encrypt(inputBlock, outputBlock, inputLength, &key, iv, AES_ENCRYPT); // 解密过程 AES_set_decrypt_key(userKey, KEY_LENGTH, &key); AES_cbc_decrypt(inputBlock, outputBlock, inputLength, &key, iv, AES_DECRYPT); ``` 以上是使用C语言中的AES算法ECBCBC模式进行加解密的简要示例。实际应用中需要根据具体需求和环境调整代码,并使用合适的加密库函数。 ### 回答3: EBC(电子密码本模式)和CBC(密码块链接模式)是C语言AES加解密算法中常用的两种模式。 EBC模式是最简单的模式之一,它将待加密的数据分成多个固定大小的块,然后对每个块进行独立加密。这意味着相同的输入将会得到相同的输出,因此EBC模式容易受到密码分析的攻击。此外,如果原始数据中存在重复的模式,加密后的结果也会呈现出类似的重复模式CBC模式在EBC模式的基础上增加了一个初始化向量(IV)的概念,它将每个明文块进行异或操作后再加密。首先,对第一个明文块进行异或操作时,使用的是IV。然后,将加密结果作为下一块明文的一部分与之进行异或操作。这样做的好处是,即使明文块中存在相同的内容,通过与前一个块进行异或操作,加密后的输出也会随机化,难以被密码分析攻击者识别。 在CBC模式中,解密操作是加密操作的逆过程。首先,对密文块进行解密,然后与前一个密文块进行异或操作,得到明文块。 总的来说,CBC模式比EBC模式更安全,因为它引入了随机性和反馈机制,使得相同的明文块加密后得到不同的密文块。这样可以更好地保护数据的安全性。但需要注意的是,在使用CBC模式时,要确保每个块都是独立的,否则可能会导致数据的安全性降低。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值