美文网首页
Java 实现 DES 加密

Java 实现 DES 加密

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

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


目录

  • DES 简介
  • 代码实现
    • ECB
    • CBC
    • CTR

DES 简介

DES(Data Encryption Standard,数据加密标准)是一种对称加密算法,目前已经不是一种安全的加密方法,因为使用的秘钥过短。
DES 算法的入口参数有三个:

  • Key:8 字节共 64 位,是 DES 算法的工作密钥。
  • Data:8 字节共 64 位,需要被加解密的数据。
  • Mode:DES 工作方式,加密或解密。

五种分组模式:EBC(电子密码本)、CBC(加密分组链接)、CFB(加密反馈模式)、OFB(输出反馈)、CTR。
其中 CTR 模式被广泛用于 ATM 网络安全和 IPSec 应用中,相对于其它模式,CTR 模式具有以下特点:

  • 硬件效率:允许同时处理多块明文和密文。
  • 软件效率:允许并行计算,可以很好地利用 CPE 流水等并行技术。
  • 预处理:算法和加密盒的输出不依赖于明文和密文的输入,因此如果有足够的保证安全的存储器,加密算法将仅仅是一系列异或运算,这将极大地提高吞吐量。
  • 随机访问:第 i 块密文的解密不依赖于第 i-1 块密文,提供很高的随机访问能力。
  • 可证明的安全性:能够证明 CTR 至少和其他模式一样安全。
  • 简单性:与其它模式不同,CTR 模式仅要求实现加密算法,但不要求实现解密算法。对于 AES 等加解密本质上不同的算法来说,这种简化是巨大的。
  • 无填充,可以高效地作为流式加密使用。

Java 实现 DES 对称加密算法时常采用的是 NoPadding(不填充)、Zeros 填充(0填充) 和 PKCS5Padding 填充。


代码实现

ECB
package tutorial.java.util;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;

public class DesUtils {

    /**
     * 算法名称
     */
    private static final String ALGORITHM_DES = "DES";

    /**
     * ECB 模式加密
     *
     * @param key     密钥
     * @param content 加密原文
     * @param padding 填充模式
     * @return 加密后字符数组
     */
    public static byte[] encryptEcb(byte[] key, byte[] content, Padding padding) {
        try {
            // 生成密钥
            Key desKey = keyGenerator(key);
            // 实例化一个 Cipher 对象用于完成加密操作
            Cipher cipher = Cipher.getInstance(ALGORITHM_DES + "/ECB/" + padding.value);
            // 初始化 Cipher 对象,设置为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, desKey, new SecureRandom());
            return cipher.doFinal(content);
        } catch (InvalidKeyException e) {
            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");
        }
    }

    /**
     * ECB 模式解密
     *
     * @param key     密钥
     * @param content 密文
     * @param padding 填充模式
     * @return 原文字符数组
     */
    public static byte[] decryptEcb(byte[] key, byte[] content, Padding padding) {
        try {
            // 生成密钥
            Key desKey = keyGenerator(key);
            // 实例化一个 Cipher 对象用于完成解密操作
            Cipher cipher = Cipher.getInstance(ALGORITHM_DES + "/ECB/" + padding.value);
            // 初始化 Cipher 对象,设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, desKey);
            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) {
            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");
        }
    }

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

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

        private String value;

        Padding(String value) {
            this.value = value;
        }
    }
}

单元测试

package tutorial.java.util;

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

import java.nio.charset.StandardCharsets;

public class DesUtilsTest {

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

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

    @Test
    public void testEcbPkcs5Padding() {
        // 密钥长度必须是 8 的倍数
        String key = "12345678";
        String content = "123456789";
        test(DesUtils.Padding.PKCS5_PADDING, key, content);
    }
}
CBC
package tutorial.java.util;

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

public class DesUtils {

    /**
     * 算法名称
     */
    private static final String ALGORITHM_DES = "DES";

    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));

    /**
     * CBC 模式加密
     *
     * @param key     密钥
     * @param content 加密原文
     * @param padding 填充模式
     * @return 加密后字符数组
     */
    public static byte[] encryptCbc(byte[] key, byte[] content, Padding padding) {
        try {
            // 生成密钥
            Key desKey = keyGenerator(key);
            // 实例化一个 Cipher 对象用于完成加密操作
            Cipher cipher = Cipher.getInstance(ALGORITHM_DES + "/CBC/" + padding.value);
            // 初始化 Cipher 对象,设置为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, desKey, IV_PARAMETER_SPEC);
            return cipher.doFinal(content);
        } catch (InvalidKeyException e) {
            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");
        }
    }

    /**
     * CBC 模式解密
     *
     * @param key     密钥
     * @param content 密文
     * @param padding 填充模式
     * @return 原文字符数组
     */
    public static byte[] decryptCbc(byte[] key, byte[] content, Padding padding) {
        try {
            // 生成密钥
            Key desKey = keyGenerator(key);
            // 实例化一个 Cipher 对象用于完成解密操作
            Cipher cipher = Cipher.getInstance(ALGORITHM_DES + "/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) {
            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");
        }
    }

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

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

        private String value;

        Padding(String value) {
            this.value = value;
        }
    }
}

单元测试

package tutorial.java.util;

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

import java.nio.charset.StandardCharsets;

public class DesUtilsTest {

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

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

    @Test
    public void testCbcPkcs5Padding() {
        // 密钥长度必须是 8 的倍数
        String key = "12345678";
        String content = "123456789";
        test(DesUtils.Padding.PKCS5_PADDING, key, content);
    }
}
CTR
package tutorial.java.util;

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

public class DesUtils {

    /**
     * 算法名称
     */
    private static final String ALGORITHM_DES = "DES";

    private static final SecureRandom RANDOM = new SecureRandom();

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

    /**
     * CTR 模式加密
     *
     * @param key     密钥
     * @param content 加密原文
     * @param padding 填充模式
     * @return 加密后字符数组
     */
    public static byte[] encryptCtr(byte[] key, byte[] content, Padding padding) {
        try {
            // 生成密钥
            Key desKey = keyGenerator(key);
            // 实例化一个 Cipher 对象用于完成加密操作
            Cipher cipher = Cipher.getInstance(ALGORITHM_DES + "/CTR/" + padding.value);
            // 初始化 Cipher 对象,设置为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, desKey, IV_PARAMETER_SPEC);
            return cipher.doFinal(content);
        } catch (InvalidKeyException e) {
            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");
        }
    }

    /**
     * CTR 模式解密
     *
     * @param key     密钥
     * @param content 密文
     * @param padding 填充模式
     * @return 原文字符数组
     */
    public static byte[] decryptCtr(byte[] key, byte[] content, Padding padding) {
        try {
            // 生成密钥
            Key desKey = keyGenerator(key);
            // 实例化一个 Cipher 对象用于完成解密操作
            Cipher cipher = Cipher.getInstance(ALGORITHM_DES + "/CTR/" + 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) {
            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");
        }
    }

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

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

        private String value;

        Padding(String value) {
            this.value = value;
        }
    }
}

单元测试

package tutorial.java.util;

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

import java.nio.charset.StandardCharsets;

public class DesUtilsTest {

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

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

    @Test
    public void testCtrPkcs5Padding() {
        // 密钥长度必须是 8 的倍数
        String key = "12345678";
        String content = "123456789";
        test(DesUtils.Padding.PKCS5_PADDING, key, content);
    }
}

相关文章

  • Java 实现 DES 加密

    本文介绍 Java 语言实现 DES 加密的方法。 目录 DES 简介 代码实现ECBCBCCTR DES 简介 ...

  • Java实现加密

    DES加密示例 其他文档:Java实现加密[https://www.cnblogs.com/caizhaokai/...

  • Java 实现 3DES 加密

    本文介绍 Java 语言实现 3DES 加密的方法。 目录 3DES 简介 代码实现CBC 3DES 简介 3DE...

  • Des

    常用加密算法的Java实现总结 对称加密算法DES、3DES和AES 算法原理DES算法把64位的明文输入块变为6...

  • 2.2 DES/3DES算法Java用法

    对称加密技术 - DES系列的Java用法 Java中的用法 JDK仅仅提供了针对56位密钥长度的DES算法实现,...

  • crypto-js实现加密解密

    1、DES加密 2、DES解密 3、AES加密 4、AES解密 5、注意:js的前端加密不能与java加密代码写的...

  • Java 常用加密算法(二)---对称加密(DES/3DES(T

    Java 常用加密算法(二)---对称加密(DES/3DES(TripleDES)/AES) 基于“对称密钥”的加...

  • DES加密 解密 java和iOS 保持一致

    1.java/android DES加密解密 base64编码用的jdk1.8 2.iOS DES加密解密

  • Android Des/3DES加解密

    1、3DES加解密 DES加密分为 单DES和 3DES加密 单DES加密是8个字节长度加密 3DES加密分为:双...

  • java DES 加密

    注意:1、DES加密时 key长度大于82、 transformation 为"DES/ECB/PKCS7Padd...

网友评论

      本文标题:Java 实现 DES 加密

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