AES下的ECB对称加密工具类,仅传字符串即可。

本文介绍了如何使用AES对称加密算法在Java中实现字符串的加解密。通过修改原始代码,将加密后的byte数组转换为16进制字符串,解决了在显示、存储和传输过程中不便使用的问题。提供了加密和解密的工具类,便于操作。注意,秘钥长度必须是16位的倍数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近想要对字符串加密,但又不需要太严格的,于是就想到了对称加密,百度一搜,正好就搜索到了廖雪峰老师的代码。自己在使用中遇到并解决了一些问题。记录一下。

以下是老师的源码:

import java.security.*;
import java.util.Base64;

import javax.crypto.*;
import javax.crypto.spec.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // 原文:
        String message = "Hello, world!";
        System.out.println("Message: " + message);
        // 128位密钥 = 16 bytes Key:
        byte[] key = "1234567890abcdef".getBytes("UTF-8");
        // 加密:
        byte[] data = message.getBytes("UTF-8");
        byte[] encrypted = encrypt(key, data);
        System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encrypted));
        // 解密:
        byte[] decrypted = decrypt(key, encrypted);
        System.out.println("Decrypted: " + new String(decrypted, "UTF-8"));
    }

    // 加密:
    public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKey keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        return cipher.doFinal(input);
    }

    // 解密:
    public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKey keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        return cipher.doFinal(input);
    }
}

运行当然没有问题,效果也很好。但使用之后发现并不是很顺手。问题出在了这:

// 加密:
        byte[] data = message.getBytes("UTF-8");
        byte[] encrypted = encrypt(key, data);
        System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encrypted));
        // 解密:可以看到解密是直接把加密出来的byte[]型数据进行解密。
        byte[] decrypted = decrypt(key, encrypted);

可以看到解密中传入的第二个参数是直接把加密出来的byte[]型数据传入进行解密。这里如果对encrypted进行.toString、String.ValueOf、Base64.getEncoder().encodeToString()等字符串强转再用getBytes(“UTF-8”)转回byte型放进decrypt()中解密,jvm将会报错,而我们肯定不会加完密就解密,通常要进行显示、存储、传输,这时候用byte[]类型就显得有些别扭,如果能全程使用字符串进行加解密,想必会非常顺手。于是我开始研究,显然加密后的byte数组是不能强制转换成字符串的,所以我们将二进制数据转换成十六进制表示然后需要的时候再转回来即可,再略加修改得到以下工具类:

import java.security.*;
import java.util.Base64;

import javax.crypto.*;
import javax.crypto.spec.*;

/**
 * Created by bob
 * Date : 21-9-10
 * Describe :
 */
public class testutil {

    // 加密:
    public static String encrypt(String key, String input) throws Exception {
        byte[] mKey = key.getBytes(StandardCharsets.UTF_8);
        byte[] data = input.getBytes(StandardCharsets.UTF_8);
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKey keySpec = new SecretKeySpec(mKey, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        return parseByte2HexStr(cipher.doFinal(data));
    }

    // 解密:
    public static String decrypt(String key, String input) throws Exception {
        byte[] mKey = key.getBytes(StandardCharsets.UTF_8);
        byte[] data = parseHexStr2Byte(input);
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKey keySpec = new SecretKeySpec(mKey, "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        return new String(cipher.doFinal(data), StandardCharsets.UTF_8);
    }

    /**
     * 将二进制转换成16进制
     *
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }


    /**
     * 将16进制转换为二进制
     *
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

}

经过略微修改后,就完成了上述工具类,非常方便,加密只需要调用encrypt(秘钥,内容);就能返回加密后的字符串,解密只需要调用decrypt(秘钥,加密后的内容);就能返回解密后也就是加密前的内容【哦,这里提个醒,秘钥必须是16位的倍数(16、32、…)。】全程传字符串类型就好了,非常方便。

参考1:JAVA实现AES 解密报错Input length must be multiple of 16 when decrypting with padded cipher
参考2:廖雪峰对称加密算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值