美文网首页
Java 实现 3DES 加密

Java 实现 3DES 加密

作者: 又语 | 来源:发表于2020-04-10 19:58 被阅读0次

本文介绍 Java 语言实现 3DES 加密的方法。


目录

  • 3DES 简介
  • 代码实现
    • CBC

3DES 简介

3DES,原名 Triple Data Encryption Algorithm,即 三重数据加密算法,缩写也为 TDEA。
3DES 是对原版 DES 的改进,相当于对每个数据块应用 3 次 DES算法,是 DES 向 AES 过渡的加密算法。
3DES 的加密过程:C=EK3(DK2(EK1(M)))
3DES 的解密过程:M=DK1(EK2(DK3(C)))
C 是密文,M 是明文,K 代表 DES 算法使用的密钥,EK() 代表 DES 算法的加密过程,DK() 代表 DES 算法的解密过程。


代码实现

CBC
  1. 添加 Bouncy Castle 依赖
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.65</version>
</dependency>
  1. 代码
package tutorial.java.util;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.*;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.*;
import java.security.spec.InvalidKeySpecException;

public class TripleDesUtils {

    /**
     * 算法名称
     */
    private static final String ALGORITHM_3DES = "DESEDE";

    private static final SecureRandom RANDOM = new SecureRandom();

    /**
     * 注意:
     * 1.CBC 模式下加解密 Cipher 初始化必须传入同一个 IvParameterSpec 实例参数
     * 2.IvParameterSpec 构造函数中参数字节数组长度必须是 8 位
     */
    private static final IvParameterSpec IV_PARAMETER_SPEC = new IvParameterSpec(RANDOM.generateSeed(8));

    public static byte[] encryptCbc(byte[] key, byte[] content, Padding padding) {
        // 添加一个安全供应商
        Security.addProvider(new BouncyCastleProvider());
        // 生成密钥
        try {
            Key desKey = keyGenerator(key);
            // 实例化一个 Cipher 对象用于完成加密操作
            Cipher cipher = Cipher.getInstance(ALGORITHM_3DES + "/CBC/" + padding.value);
            // 初始化 Cipher 对象,设置为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, desKey, IV_PARAMETER_SPEC);
            return cipher.doFinal(content);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new UnsupportedOperationException("Invalid Key");
        } catch (NoSuchAlgorithmException e) {
            throw new UnsupportedOperationException("No such algorithm");
        } catch (InvalidKeySpecException e) {
            throw new UnsupportedOperationException("Invalid key spec");
        } catch (NoSuchPaddingException e) {
            throw new UnsupportedOperationException("No such padding");
        } catch (BadPaddingException e) {
            throw new UnsupportedOperationException("Bad padding");
        } catch (IllegalBlockSizeException e) {
            throw new UnsupportedOperationException("Illegal block size");
        } catch (InvalidAlgorithmParameterException e) {
            throw new UnsupportedOperationException("Illegal algorithm parameter");
        }
    }

    public static byte[] decryptCbc(byte[] key, byte[] content, Padding padding) {
        try {
            // 生成密钥
            Key desKey = keyGenerator(key);
            // 实例化一个 Cipher 对象用于完成解密操作
            Cipher cipher = Cipher.getInstance(ALGORITHM_3DES + "/CBC/" + padding.value);
            // 初始化 Cipher 对象,设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, desKey, IV_PARAMETER_SPEC);
            return cipher.doFinal(content);
        } catch (NoSuchPaddingException e) {
            throw new UnsupportedOperationException("No such padding");
        } catch (NoSuchAlgorithmException e) {
            throw new UnsupportedOperationException("No such algorithm");
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new UnsupportedOperationException("Invalid Key");
        } catch (InvalidKeySpecException e) {
            throw new UnsupportedOperationException("Invalid key spec");
        } catch (BadPaddingException e) {
            throw new UnsupportedOperationException("Bad padding");
        } catch (IllegalBlockSizeException e) {
            throw new UnsupportedOperationException("Illegal block size");
        } catch (InvalidAlgorithmParameterException e) {
            throw new UnsupportedOperationException("Illegal algorithm parameter");
        }
    }

    /**
     * 生成 3DES 密钥对象
     *
     * @param key 密钥字节数组
     * @return 密钥对象
     * @throws InvalidKeyException      Key 无效
     * @throws NoSuchAlgorithmException 无相关算法
     * @throws InvalidKeySpecException  KeySepc 无效
     */
    private static Key keyGenerator(byte[] key)
            throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException {
        DESedeKeySpec deSedeKeySpec = new DESedeKeySpec(key);
        // 创建一个密钥工厂,用于转换 DESKeySpec
        SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM_3DES);
        // 生成一个密钥并返回
        return secretKeyFactory.generateSecret(deSedeKeySpec);
    }

    public static enum Padding {
        NO_PADDING("NoPadding"),
        PKCS5_PADDING("PKCS5Padding");

        private String value;

        Padding(String value) {
            this.value = value;
        }
    }
}
  1. 单元测试
package tutorial.java.util;

import org.junit.Assert;
import org.junit.Test;

import java.nio.charset.StandardCharsets;

public class TripleDesUtilsTest {

    private void test(TripleDesUtils.Padding padding, String key, String content) {
        byte[] encryptResult = TripleDesUtils.encryptCbc(key.getBytes(StandardCharsets.UTF_8),
                content.getBytes(StandardCharsets.UTF_8),
                padding);
        byte[] decryptResult = TripleDesUtils.decryptCbc(key.getBytes(StandardCharsets.UTF_8),
                encryptResult,
                padding);
        Assert.assertEquals(content, new String(decryptResult, StandardCharsets.UTF_8));
    }

    @Test
    public void testCbcNoPadding() {
        // 密钥长度必须是 8 的倍数,最少 24 位
        String key = "123456781234567812345678";
        // 待加密原文长度必须是 8 的倍数
        String content = "12345678";
        test(TripleDesUtils.Padding.NO_PADDING, key, content);
    }

    @Test
    public void testCbcPkcs5Padding() {
        // 密钥长度必须是 8 的倍数,最少 24 位
        String key = "123456781234567812345678";
        String content = "123456789";
        test(TripleDesUtils.Padding.PKCS5_PADDING, key, content);
    }
}

相关文章

网友评论

      本文标题:Java 实现 3DES 加密

      本文链接:https://www.haomeiwen.com/subject/fsldmhtx.html