欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DES

程序员文章站 2024-03-14 13:42:16
...

DES 算法简介

DES 加密算法属于对称密码范畴,那么什么是对称密码呢?加密和解密过程中所使用的**相同,就是对称密码,而且大多数对称密码算法,加密解密过程都是互逆的。DES 算法是一种数据加密算法,明文按照 64 位进行分组,分组后的明文与**按位替代或交换的方法形成密文组。 **的长度是 64 位(其实是56位,其中有8位是奇偶校验位)。

DES 工作模式简介

1 . ECB(电子密码密码本模式)

这是最原始的一种加密工作模式,将明文分组成64位,与**长度相同,然后按照加密算法加密,得到 64位密文,最后将所有加密后的密文连接在一起即可,各段之间互不影响(当最后一段不足64位是要补足64位在进行计算)

可见,这种模式的优点是实现起来简单,有利于并行运算,但是缺点是安全性比较低。

2 . CBC (密文链接模式)

这种模式相比于 ECB 就比较复杂了,让我们来看看它是如何加密的

    1. 首先将数据按照8个字节一组进行分组得到D1D2......Dn(若数据不是8的整数倍,用指定的PADDING数据补位)
    2. 第一组数据D1与初始化向量I异或后的结果进行DES加密得到第一组密文C1(初始化向量I为全零)
    3. 第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2
    4. 之后的数据以此类推,得到Cn
    5. 按顺序连为C1C2C3......Cn即为加密结果。

这种加密模式相比于上一中比较安全一些,但是有一个致命的缺点,就是误差延续性,就是说只要有一个地方的密文出现错误,那么底下的密文就都会出现错误,为什么会这样?仔细看看加密过程就能明白,这也就是为什么这种模式叫做链接模式。

当然还有其他的模式,就不一一介绍了,一般还是利用以上两种模式。

DES 填充模式

  NoPadding    
  API或算法本身不对数据进行处理,加密数据由加密双方约定填补算法。例如若对字符串数据进行加解密,可以补充\0或者空格,然后trim。

   PKCS5Padding   
   加密前:数据字节长度对8取余,余数为m,若m>0,则补足8-m个字节,字节数值为8-m,即差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8

填充模式就用于当明文不是64的倍数的时候,由于在加密的过程中需要对明文进行分块,所以需要选择填充模式。

DES 的使用

1 . 和 Hmac 算法一样,想要使用 DES,首先要获取**,这需要借助于 JDK 自带的 KeyGenerator

public static byte[] initKey() throws Exception {
    KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
    keyGenerator.init(56); // 56 可填可不填

    SecretKey secretKey = keyGenerator.generateKey();
    return secretKey.getEncoded();
}

2 . 接下来就是 DES 加密过程

public static byte[] encryptDES(byte[] key, byte[] data) throws Exception {

        SecretKey secretKey = new SecretKeySpec(key, "DES");

        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] resultBytes = cipher.doFinal(data);
        return resultBytes;

    }

传进去一个 helloworld 看看结果

public static void main(String[] args) throws Exception {
        String data = "helloworld";
        byte[] key = initKey();

        byte[] resultBytes = encryptDES(key, data.getBytes());

        String resultString = byteToHexString(resultBytes);

        System.out.println(resultString);

    }

结果为

215f9748bf31d5dc3d4eb5b77107643b

既然 DES 是用于数据加密,那么我们总应该能把数据还原成明文把,不然其意义何在呢?其实解密过程和加密过程几乎一模一样,如下所示

public static String decryptDES(byte[] key, byte[] data) throws Exception {
        SecretKey secretKey = new SecretKeySpec(key, "DES");

        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);

        byte[] resultBytes = cipher.doFinal(data);

        return new String(resultBytes);
    }

这个时候传进来的 key 必须和加密时使用的 key 是相同的,而且这个时候传进来的 data 也必须是加密过后的密文。

咦,这个时候我们发现,我们开头介绍的加密模式和填充模式好像都没用到,其实我们一般是使用默认就可以了,如果有特殊需要,可以这样使用

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

DES加密过后的数据在以前是不可能被**的,但是由于计算机的发展,DES 加密过得数据在如今完全可在24小时内被**,所以在 DES 的基础上有延伸出了 3DES 和 AES,这两种算法将留到以后再介绍~