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]
//        解密后的内容:各位辛苦了
    }
}

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
AES(Advanced Encryption Standard,高级加密标准)是一种对称加密算法,常用于数据加密和解密。而CBC(Cipher Block Chaining,密码块链)模式是一种加密算法的工作模式PKCS5Padding是填充模式,用于将不满整块长度的数据进行填充,以满足加密算法的要求。 在使用H5进行AES CBC PKCS5Padding算法解密时,我们首先需要准备好密钥和加密后的数据。密钥可以是一个字符串,而加密后的数据通常是经过Base64编码的字符串。 接下来,我们需要将Base64编码的字符串解码成二进制数据,并将解码后的数据进行分块。每个分块的长度应该与密钥的长度相同,通常为16字节(128位)。如果数据的长度不是密钥长度的整数倍,我们可以使用PKCS5Padding进行填充。 然后,我们需要使用AES算法和CBC工作模式创建一个解密器。解密器需要接收密钥和初始向量(IV)作为参数。初始向量是一个随机生成的数据块,用于与第一个分块进行异或运算。 接下来,我们可以以分块的形式将加密数据输入到解密器中,并获得解密后的数据。解密器会自动对数据进行解密和去除填充。 最后,我们可以将解密后的数据转换回字符串形式,以得到我们想要的明文。 需要注意的是,在使用H5进行AES CBC PKCS5Padding算法解密时,我们需要确保密钥的正确性,以及正确的数据分块和填充。如果出现了错误,可能导致解密失败或明文数据损坏。因此,在使用这种算法进行数据加密和解密时,建议仔细检查每个步骤的实现,并保持与其他参与方的一致性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值