AES加密工具类坑

正确代码如下:

package org.springblade.common.utils;


import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class AESDecryptionExample {
    //加密
    public static String aesEncrypt(String key, String encryptStr) {
        byte[] encodedKey = key.getBytes(StandardCharsets.UTF_8);
        SecretKeySpec secretKeySpec = new SecretKeySpec(encodedKey, "AES");
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            byte[] encryptedBytes = cipher.doFinal(encryptStr.getBytes(StandardCharsets.UTF_8));
            String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
            System.out.println("加密后的文本:" + encryptedText);
            return encryptedText;
        } catch (IllegalBlockSizeException e) {
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    public static String aesDEncrypt(String key,String encryptStr){
        byte[] encodedKey = key.getBytes(StandardCharsets.UTF_8);
        SecretKeySpec secretKeySpec = new SecretKeySpec(encodedKey, "AES");
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("AES");
            // 解密
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);

            byte[] decryptedBytes = new byte[0];
            decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptStr));

            String decryptedText = new String(decryptedBytes, StandardCharsets.UTF_8);
            System.out.println("解密后的文本:" + decryptedText);
            return decryptedText;
        } catch (IllegalBlockSizeException e) {
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
}

异常代码如下:

package com.ctf.mall.utils;


import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * @PACKAGE_NAME: com.ctf.mall.common.utils
 * @NAME: AESDecryptionExample
 * @author: 周政
 * @since: Created on 2024年03月26日 15:43
 * @DESCRIPTION: 手机号加解密工具
 */
public class AESDecryptionExample {
    //加密
    public static String aesEncrypt(String key, String encryptStr) {
        byte[] encodedKey = key.getBytes(StandardCharsets.UTF_8);
        SecretKeySpec secretKeySpec = new SecretKeySpec(encodedKey, "AES");
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] ivBytes = new byte[16]; // 初始化向量(IV)必须与块大小一致,对于AES使用128位的块,因此IV长度为16字节
            IvParameterSpec iv = new IvParameterSpec(ivBytes);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
            byte[] encryptedBytes = cipher.doFinal(encryptStr.getBytes(StandardCharsets.UTF_8));
            String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
            System.out.println("加密后的文本:" + encryptedText);
            return encryptedText;
        } catch (IllegalBlockSizeException e) {
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {
            throw new RuntimeException(e);
        } catch (InvalidAlgorithmParameterException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    public static String aesDEncrypt(String key,String encryptStr){
        byte[] encodedKey = key.getBytes(StandardCharsets.UTF_8);
        SecretKeySpec secretKeySpec = new SecretKeySpec(encodedKey, "AES");
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] ivBytes = new byte[16]; // 初始化向量(IV)必须与块大小一致,对于AES使用128位的块,因此IV长度为16字节
            IvParameterSpec iv = new IvParameterSpec(ivBytes);
            // 解密
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, iv);

            byte[] decryptedBytes = new byte[0];
            decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptStr));

            String decryptedText = new String(decryptedBytes, StandardCharsets.UTF_8);
            System.out.println("解密后的文本:" + decryptedText);
            return decryptedText;
        } catch (IllegalBlockSizeException e) {
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {
            throw new RuntimeException(e);
        } catch (InvalidAlgorithmParameterException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
}

问题现象:手机号(数字)加解密正常,中文(湖北省-武汉市-洪山区-东湖高新中建大公馆3期B9号楼1单元12楼1202)和别的.net系统生成的加密后的值不一致,并且解密失败报异常;

异常信息:Exception in thread "main" java.lang.RuntimeException: javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
    at com.ctf.mall.utils.AESDecryptionExample.aesDEncrypt(AESDecryptionExample.java:73)
    at com.ctf.mall.utils.AESDecryptionExample.main(AESDecryptionExample.java:88)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:991)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
    at javax.crypto.Cipher.doFinal(Cipher.java:2164)
    at com.ctf.mall.utils.AESDecryptionExample.aesDEncrypt(AESDecryptionExample.java:65)
    ... 1 more

错误原因:因为获取Cipher实例的时候用了多种方式"AES/CBC/PKCS5Padding",而IvParameterSpec这个入参应该是CBC还是DES才用到的导致加解密异常;

区别位置参考:获取实例位置和捕捉异常位置

cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] ivBytes = new byte[16]; // 初始化向量(IV)必须与块大小一致,对于AES使用128位的块,因此IV长度为16字节
            IvParameterSpec iv = new IvParameterSpec(ivBytes);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值