3DES加密工具类


import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.spec.KeySpec;

/**
 * 3DES加密工具类
 *
 */
@Slf4j
public class DES3Utils {

    /**
     * 随意定一个私钥(长度必须为24位) 固定密钥字符串
     */
    public static final String FIXED_KEY_STRING = "@@111111111IJKLMN123456E";

    /**
     * 加密
     *
     * @param inStr     需要加密的内容
     * @param secretKey 密钥
     * @return 加密后的数据
     */
    public static String encrypt(String inStr, String secretKey) throws Exception {
        SecretKey desKey = generateKey(secretKey);
        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); // 明确分组和填充模式
        cipher.init(Cipher.ENCRYPT_MODE, desKey);
        byte[] encryptedBytes = cipher.doFinal(inStr.getBytes(StandardCharsets.UTF_8));
        return byte2hex(encryptedBytes);
    }

    /**
     * 解密
     *
     * @param inStr     需要解密的内容
     * @param secretKey 密钥
     * @return 解密后的数据
     */
    public static String decrypt(String inStr, String secretKey) throws Exception {
        SecretKey desKey = generateKey(secretKey);
        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, desKey);
        byte[] decryptedBytes = cipher.doFinal(hex2byte(inStr));
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    private static SecretKey generateKey(String keyStr) throws Exception {
        KeySpec keySpec = new DESedeKeySpec(keyStr.getBytes(StandardCharsets.UTF_8));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
        return keyFactory.generateSecret(keySpec);
    }


    /**
     * 转化为16进制字符串方法
     *
     * @param digest 需要转换的字节组
     * @return 转换后的字符串
     */
    private static String byte2hex(byte[] digest) {
        StringBuffer hs = new StringBuffer();
        String stmp = "";
        for (int n = 0; n < digest.length; n++) {
            stmp = Integer.toHexString(digest[n] & 0XFF);
            if (stmp.length() == 1) {
                hs.append("0" + stmp);
            } else {
                hs.append(stmp);
            }
        }

        return hs.toString().toUpperCase();
    }

    /**
     * 十六进转二进制
     *
     * @param hexStr 待转换16进制字符串
     * @return 二进制字节组
     */
    public static byte[] hex2byte(String hexStr) {
        if (hexStr == null)
            return null;
        hexStr = hexStr.trim();
        int len = hexStr.length();
        if (len == 0 || len % 2 == 1)
            return null;
        byte[] digest = new byte[len / 2];
        try {
            for (int i = 0; i < hexStr.length(); i += 2) {
                digest[i / 2] = (byte) Integer.decode("0x" + hexStr.substring(i, i + 2)).intValue();
            }
            return digest;
        } catch (Exception e) {
            return null;
        }

    }

    public static void main(String[] args) {

        try {
             
            String cdkey = "XXXXXXXXXXXXXXX";
            // key需要24位
            String s1 = encrypt(cdkey, "@@111111111IJKLMN123456E");
            System.out.println("Encrypted: " + s1);

            String s2 = decrypt(s1, "@@111111111IJKLMN123456E");
            System.out.println("Decrypted: " + s2);
        } catch (Exception e) {
            // 异常处理
            log.error("异常情况:{}", e);
        }

    }

}

这个Java类DES3Utils是一个用于执行3DES(Triple Data Encryption Standard,即三重数据加密算法)加密和解密操作的工具类。下面是对该类功能和重要部分的详细解析:

类定义与常量

  • 类注解 @Slf4j: 引入Lombok库的注解,自动为类添加日志记录功能,简化日志记录代码。
  • 常量 FIXED_KEY_STRING: 定义了一个固定的24字符长度的密钥字符串,用于3DES算法。3DES要求密钥长度为24字节(即192位),因为它实际上执行三次DES加密,每次需要8字节密钥。

加密方法 encrypt(String inStr, String secretKey)

  1. 密钥生成: 调用generateKey(String keyStr)方法,根据传入的密钥字符串生成一个SecretKey对象。这里通过DESedeKeySpec指定密钥材料,然后利用SecretKeyFactory创建密钥实例。
  2. Cipher实例化: 使用Cipher.getInstance("DESede/ECB/PKCS5Padding")获取一个Cipher对象,指定算法模式为ECB(Electronic Codebook,电子密码本模式),填充模式为PKCS5Padding。
  3. 初始化Cipher: 根据密钥和加密模式初始化Cipher实例。
  4. 执行加密: 调用doFinal方法对输入字符串的字节表示进行加密,得到加密后的字节数组。
  5. 转换输出: 将加密后的字节数组通过byte2hex方法转换为16进制字符串,便于显示和存储。

解密方法 decrypt(String inStr, String secretKey)

解密过程与加密类似,但操作相反:

  • 初始化Cipher为解密模式。
  • 使用相同的密钥和填充模式。
  • 将输入的16进制字符串通过hex2byte转换回字节数组。
  • 执行解密并转换回字符串输出。

辅助方法

  • generateKey(String keyStr): 用于从给定的字符串密钥生成SecretKey
  • byte2hex(byte[] digest): 将字节数组转换成大写的16进制字符串。
  • hex2byte(String hexStr): 将16进制字符串转换回字节数组。

发现 key的前24是起作用的 24位之后更改字符不会影响解析效果(第24位如果是前后2个字符也不影响解析效果)

这个问题涉及到3DES(Triple DES)算法的密钥结构和处理方式。3DES是一种对称加密算法,它是基于原来的DES算法扩展而来,通过使用三个不同的密钥对数据进行三次加密(或者加密-解密-加密步骤)处理,来提高安全性。

在3DES中,密钥长度可以是168位(即24字节)或者192位(24字节密钥在实际处理时会扩展到192位)。具体来说:

  • 当使用168位密钥时,实际上密钥会被分成两部分,每部分8字节,然后在内部处理中会生成第三部分密钥作为中间密钥,这样总共还是进行三次加密操作。
  • 如果提供的是24字节密钥,这24字节会被直接分为三段,每8字节一段,分别作为三次加密的密钥。

当你提到“key的前24位是起作用的,24位之后更改字符不会影响解析效果”,这很可能是因为在你的实现中,虽然你提供了超过24位的密钥,但实际使用的只是前24位(三个8字节的部分),超出的部分被忽略了。这是因为DESede/ECB/PKCS5Padding模式在处理密钥时,只会使用前24字节来生成实际的加密密钥,多余的字符不会参与密钥生成过程,因此更改它们不影响加密和解密的结果。

此外,关于“第24位如果是前后2个字符也不影响解析效果”的描述可能是指,在某些情况下,即使第24位字符及其前后有变化(比如字符被误写或修改),如果这些变化没有导致密钥的有效部分(即前24位)发生改变,加密和解密的过程仍然能够正确进行,因为真正用于加密的密钥部分保持不变。

总之,这种现象是因为3DES算法仅使用密钥的特定部分(最多24字节,按8字节分段),超出这个长度的密钥部分在你的实现中未被使用,所以不会影响加密解密过程。在设计和实施安全系统时,应当避免使用无效或冗余的密钥材料,确保密钥管理的严谨性。

DES(Data Encryption Standard)算法,其密钥长度固定为56位,即7字节。但在实际应用中,密钥通常以8字节(即64位)的形式输入,其中前7字节(56位)用于加密运算,而最后一位(第8字节的最高位)在标准的DES实现中并不使用于加密过程,有时会被设置为奇偶校验位或其他校验用途。因此,从广义上讲,可以认为DES算法处理的是基于前7个字节的有效密钥数据,尽管在软件实现中常常以8字节的形式处理和传递。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值