AES CBC PKCS5Padding加解密模式,32位密钥 和 32位向量 使用16进制转换成二进制,加解密

github代码地址:https://github.com/shenyang312/shen_cloud_platform/blob/master/code/src/main/java/com/shen/cloud/util/AESDUtile.java

1.首先是aes的cbc PKCS5Padding填充模式

现实对 对长度为 16字节的 password 进行 Hex解码

 1.1 需要把16进制串转换成2进制数组

传入的为字符串对应数组

先验证传入key长度,然后通过toDigit方法把16进制转换成整数,在偏移4位转换成二进制,放到数组

整体代码流程:

加密前准备

然后进行加密传入(注:安全性考虑理论上是需要对aes密钥进行RSA签名加密,外加一个SHAR256内容一致性校验)

代码中AES_CBC的填充方式为:PKCS5Padding,mode

Cipher.ENCRYPT_MODE

 二。加密成功进行解密 传入 

相同流程的  password 和 iv

aes方法中 传入 Cipher.DECRYPT_MODE

此时已经解密成功,转换成"utf-8"字符串即可

package com.shen.cloud.util;

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.util.Arrays;

/**
 * 本示例提供AES(128位)算法加密和解密演示
 * AES 128位算法中秘钥和向量(偏移量)长度为16个字节,需要将32位字符串使用16进制转换成二进制
 */
public class AESDUtile {

    private static final String AES = "AES";
    private static final String AES_CBC = "AES/CBC/PKCS5Padding";
    private static final char[] DIGITS_LOWER =
            {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    /**
     * 加密
     *
     * @param data 待加密明文数据
     * @param key  加密密码
     * @param iv   加密向量(偏移量)
     * @return
     */
    public static byte[] encrypt(byte[] data, byte[] key, byte[] iv) {
        return aes(data, key, iv, Cipher.ENCRYPT_MODE);
    }

    /**
     * 解密
     *
     * @param encryptedData 加密后的数据
     * @param key           解密密码
     * @param iv            解密向量(偏移量)
     * @return
     */
    public static byte[] decrypt(byte[] encryptedData, byte[] key, byte[] iv) {
        return aes(encryptedData, key, iv, Cipher.DECRYPT_MODE);
    }

    /**
     * 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
     *
     * @param input 原始字节数组
     * @param key   符合AES要求的密钥
     * @param iv    初始向量
     * @param mode  Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
     */
    private static byte[] aes(byte[] input, byte[] key, byte[] iv, int mode) {
        try {
            SecretKey secretKey = new SecretKeySpec(key, AES);
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            Cipher cipher = Cipher.getInstance(AES_CBC);
            cipher.init(mode, secretKey, ivSpec);
            return cipher.doFinal(input);
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        }
    }

    public static byte[] decodeHex(final char[] data) throws Exception {

        final int len = data.length;

        if ((len & 0x01) != 0) {
            throw new Exception("Odd number of characters.");
        }

        final byte[] out = new byte[len >> 1];

        // two characters form the hex value.
        for (int i = 0, j = 0; j < len; i++) {
            int f = toDigit(data[j], j) << 4;
            j++;
            f = f | toDigit(data[j], j);
            j++;
            out[i] = (byte) (f & 0xFF);
        }

        return out;
    }

    /**
     * Hex解码.
     */
    public static byte[] decodeHex(String input) {
        try {
            return decodeHex(input.toCharArray());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static int toDigit(final char ch, final int index) throws Exception {
        final int digit = Character.digit(ch, 16);
        if (digit == -1) {
            throw new Exception("Illegal hexadecimal character " + ch + " at index " + index);
        }
        return digit;
    }

    public static char[] encodeHex(final byte[] data, final char[] toDigits) {
        final int l = data.length;
        final char[] out = new char[l << 1];
        for (int i = 0, j = 0; i < l; i++) {
            out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
            out[j++] = toDigits[0x0F & data[i]];
        }
        return out;
    }



    public static String encodeHexString(final byte[] data) {
        return new String(encodeHex(data));
    }

    public static char[] encodeHex(final byte[] data){
        return encodeHex(data, DIGITS_LOWER);
    }

    /**
     * 生成AES密钥,可选长度为128,192,256位.
     */
    public static byte[] generateAesKey(int keysize)throws Exception {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
            keyGenerator.init(keysize);
            SecretKey secretKey = keyGenerator.generateKey();
            return secretKey.getEncoded();
        } catch (GeneralSecurityException e) {
            throw new Exception(e);
        }
    }

    public static void main(String[] args) throws Exception {
        //密码:7985c4cc0cf22caccddb0b864f79e5dd
        //向量(偏移量):e3205234a872012af4f3ac5dbd9c810c
        String password = "7985c4cc0cf22caccddb0b864f79e5dd";
        String iv = "e3205234a872012af4f3ac5dbd9c810c";

        byte[] passwordBinaryArray = AESDUtile.decodeHex(password); //passwordBinaryArray 长度为16个字节
        byte[] ivBinaryArray = AESDUtile.decodeHex(iv); //ivBinaryArray 长度为16个字节
        System.out.println(passwordBinaryArray);
        System.out.println(ivBinaryArray);
        //将明文按照utf-8编码转成二进制数组
        String plainText = "各位辛苦了";//明文
        byte[] plainTextUtf8Array = plainText.getBytes("utf-8");

        //加密
        byte[] encryptedData = AESDUtile.encrypt(plainTextUtf8Array, passwordBinaryArray, ivBinaryArray);
        System.out.println("加密后的内容:" + Arrays.toString(encryptedData));

        //解密
        byte[] decryptedData = AESDUtile.decrypt(encryptedData, passwordBinaryArray, ivBinaryArray);
        System.out.println("解密后的内容:" + Arrays.toString(decryptedData));
        System.out.println("解密后的内容:" + new String(decryptedData, "utf-8"));


        所有输出
//        加密后的内容:[-40, 91, 16, -53, 44, -92, 81, -19, 36, -51, -81, 104, -64, -40, -99, -54]
//        解密后的内容:[-27, -112, -124, -28, -67, -115, -24, -66, -101, -24, -117, -90, -28, -70, -122]
//        解密后的内容:各位辛苦了
    }
}

 

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论 2

打赏作者

狗蛋儿_312

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值