在要求输入邮箱的文本域,请填写真实的邮件地址。非真实邮件地址,将收不到回复信息。

Java实现AES加解密

JAVA 清风 20℃ 0评论

因业务需求,需要进行融合登录,根据提供融合登录方的文档内容,对AES加密解密相关内容使用.NET CORE来进行一次实现。使用.NET CORE完成后,根据文档提到的密文进行解密,很遗憾解密无法完成。最终根据提供的Java文件进行相关确认,发现文档中所表述内容与Java示例文件中出现诸多不一致的地方。最后经过咨询并确认了以Java示例文件中的内容为准,所以此处记录一下这个AES加密解密的方法。


import java.security.Key;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES加密工具类
 * 
 */
public class AESCommonUtils
{

    /** 16位向量 双方约定一致 */
    private static final String IV = "0102030504030201";

    /** 密钥 双方约定一致 */
    private static final String KEY = "3EDsw9[A4W5FdS{]3W";

    /** 加密模式及填充方式 */
    private static final String MODE_PADDING = "AES/CBC/NoPadding";

    /** 加密模式 */
    private static final String MODE = "AES";

    /** 编码格式 UTF-8 */
    private static final String CHARSET_UTF8 = "UTF-8";

    /**
     * AES加密过程
     * 
     * @param strKey
     * @return
     * @throws Exception
     */
    public static String encrypt(String strKey, String info) throws Exception {
        SecretKeySpec skeySpec = getKey(strKey);
        Cipher cipher = Cipher.getInstance(MODE_PADDING);
        int blockSize = cipher.getBlockSize();

        byte[] dataBytes = info.getBytes(CHARSET_UTF8);
        int plaintextLength = dataBytes.length;
        if (plaintextLength % blockSize != 0) {
            plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
        }

        byte[] plaintext = new byte[plaintextLength];
        System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
        IvParameterSpec iv = new IvParameterSpec(IV.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(plaintext);

        // return new BASE64Encoder().encode(encrypted);
        return byte2hex(encrypted);
    }

    /***
     * AES解密
     * 
     * @param strKey
     * @param strIn
     * @return
     * @throws Exception
     */
    public static String decrypt(String strKey, String info) throws Exception {
        try {
            byte[] byteResult = decrypt2Byte(strKey, info);
            String result = new String(byteResult, CHARSET_UTF8);
            return result;
        }
        catch (Exception e) {
            return info;
        }

    }

    /***
     * AES解密详细过程
     * 
     * @param strKey
     * @param content
     * @return
     * @throws Exception
     */
    private static byte[] decrypt2Byte(String strKey, String content) throws Exception {
        SecretKeySpec skeySpec = getKey(strKey);

        Cipher cipher = Cipher.getInstance(MODE_PADDING);
        IvParameterSpec iv = new IvParameterSpec(IV.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
        // byte[] encrypted = Base64.decode(content)
        byte[] encrypted = hex2byte(content);
        byte[] original = flushZeroElements(cipher.doFinal(encrypted));

        return original;

    }

    /**
     * 清除AES加密前补位的内容
     * 
     * @param source
     * @return
     */
    private static byte[] flushZeroElements(byte[] source) {
        int i = 0;
        for (byte b : source) {
            if (b == 0) {
                break;
            }
            i++;
        }
        byte[] result = Arrays.copyOf(source, i);
        return result;
    }

    /***
     * 针对长度不满16的密钥进行补0操作
     * 
     * @param strKey
     * @return
     * @throws Exception
     */
    private static SecretKeySpec getKey(String strKey) throws Exception {
        byte[] arrBTmp = strKey.getBytes();
        byte[] arrB = new byte[16]; // 创建一个空的16位字节数组(默认值为0)

        for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
            arrB[i] = arrBTmp[i];
        }

        SecretKeySpec skeySpec = new SecretKeySpec(arrB, MODE);

        return skeySpec;
    }

    /***
     * 把16进制转成byte类型数组
     * 
     * @param strhex
     * @return
     */
    public static byte[] hex2byte(String strhex) {
        if (strhex == null) {
            return null;
        }
        int l = strhex.length();
        if (l % 2 == 1) {
            return null;
        }
        byte[] b = new byte[l / 2];
        for (int i = 0; i != l / 2; i++) {
            b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2), 16);
        }
        return b;
    }

    /**
     * 把byte数组转成16进制
     * 
     * @param b
     * @return
     */
    public static String byte2hex(byte[] b) {
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = (Integer.toHexString(b[n] & 0XFF));
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            }
            else {
                hs = hs + stmp;
            }
        }
        return hs.toUpperCase();
    }

    public static void main(String[] args) {
        String userInfo = "11111";
        try {
                        userInfo = AESCommonUtils.encrypt(KEY,userInfo);
                        System.out.println("加密后:***" + userInfo + "===========");

                        userInfo= AESCommonUtils.decrypt(KEY,userInfo);
                        System.out.println("解密后***" + userInfo + "===========");
           
        }
        catch (Exception e) {
            System.out.println("加解密异常 : " + e.toString());
        }
    }

}

转载请注明:清风博客 » Java实现AES加解密

喜欢 (0)or分享 (0)
支付宝扫码打赏 微信打赏
发表我的评论
取消评论

CAPTCHA Image
Reload Image
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址