DES —— 数据加密标准

JAVA开发 workingTime 107℃ 0评论

timg-1

DES —— JAVA代码

二话不说,先把代码实现再学习原理!

普通DES代码如下

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * @author : R&M www.rmworking.com/blog
 *         2019/8/18 14:40
 *         jsoup_demo
 *         org.security.utils
 */
public class DESUtil {
    public static void main(String[] args) throws Exception {
        // 需要加密的数据
        String str = "qnloft.com(青柠Loft)";
        // 初始化密匙
        byte[] key = DESUtil.initKey();
        System.out.println("密匙:" + Base64.getEncoder().encodeToString(key));
        // 加密
        byte[] encryptData = DESUtil.encrypt(str.getBytes(), key);
        System.out.println("加密结果:" + Base64.getEncoder().encodeToString(encryptData));
        // 解密
        String resutl = new String(DESUtil.decrypt(encryptData, key));
        System.out.println("解密结果:" + resutl);
    }

    private static final String KEY_ALGORITHM = "DES";
    /**
     * 加解密算法/工作模式/填充方式
     */
    private static final String CIPHER_ALGORITHM_PKCS5 = "DES/ECB/PKCS5Padding";

    /**
     * 生成密匙
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static byte[] initKey() throws NoSuchAlgorithmException {
        // 实例化密匙生成器
        KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
        // 初始化密匙生成器
        kg.init(56);
        // 生成密匙
        SecretKey secretKey = kg.generateKey();
        // 二进制形式返回密匙
        return secretKey.getEncoded();
    }

    /**
     * 加密
     * @param data
     * @param key
     * @return
     */
    public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
        // 还原密匙
        Key k = toKey(key);
        // 实例化
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_PKCS5);
        // 初始化,设置为解密模式
        cipher.init(Cipher.ENCRYPT_MODE, k);
        // 执行操作
        return cipher.doFinal(data);
    }

    /**
     * 解密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
        // 还原密匙
        Key k = toKey(key);
        // 实例化
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_PKCS5);
        // 初始化,设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, k);
        // 执行操作
        return cipher.doFinal(data);
    }

    /**
     * 转换密匙
     * @param key
     * @return
     * @throws InvalidKeyException
     */
    private static Key toKey(byte[] key) throws Exception {
        // 实例化DES密匙材料
        DESKeySpec desKeySpec = new DESKeySpec(key);
        // 实例化密匙工厂
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
        // 生成密匙
        return keyFactory.generateSecret(desKeySpec);
    }

}

三重DES代码如下

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * @author : R&M www.rmworking.com/blog
 *         2019/8/25 17:28
 *         jsoup_demo
 *         org.security.utils
 */
public class DESEdeUtil {
    public static void main(String[] args) throws Exception {
        // 需要加密的数据
        String str = "qnloft.com(青柠Loft)";
        // 初始化密匙
        byte[] key = DESEdeUtil.initKey();
        System.out.println("密匙:" + Base64.getEncoder().encodeToString(key));
        // 加密
        byte[] encryptData = DESEdeUtil.encrypt(str.getBytes(), key);
        System.out.println("加密结果:" + Base64.getEncoder().encodeToString(encryptData));
        // 解密
        String resutl = new String(DESEdeUtil.decrypt(encryptData, key));
        System.out.println("解密结果:" + resutl);
    }

    private static final String KEY_ALGORITHM = "DESede";
    /**
     * 加解密算法/工作模式/填充方式
     *
     * 数据补位一般有NoPadding和PKCS7Padding(JAVA中是PKCS5Padding)填充方式
     */
    private static final String CIPHER_ALGORITHM_PKCS5 = "DESede/ECB/PKCS5Padding";

    /**
     * 生成密匙
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static byte[] initKey() throws NoSuchAlgorithmException {
        // 实例化密匙生成器
        KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
        // 初始化密匙生成器
        kg.init(168);
        // 生成密匙
        SecretKey secretKey = kg.generateKey();
        // 二进制形式返回密匙
        return secretKey.getEncoded();
    }

    /**
     * 加密
     * @param data
     * @param key
     * @return
     */
    public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
        // 还原密匙
        Key k = toKey(key);
        // 实例化
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_PKCS5);
        // 初始化,设置为解密模式
        cipher.init(Cipher.ENCRYPT_MODE, k);
        // 执行操作
        return cipher.doFinal(data);
    }

    /**
     * 解密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
        // 还原密匙
        Key k = toKey(key);
        // 实例化
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_PKCS5);
        // 初始化,设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, k);
        // 执行操作
        return cipher.doFinal(data);
    }

    /**
     * 转换密匙
     * @param key
     * @return
     * @throws InvalidKeyException
     */
    private static Key toKey(byte[] key) throws Exception {
        // 实例化DES密匙材料
        DESedeKeySpec desKeySpec = new DESedeKeySpec(key);
        // 实例化密匙工厂
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
        // 生成密匙
        return keyFactory.generateSecret(desKeySpec);
    }
}

DES填充方式说明:

  • NoPadding 填充方式:算法本身不填充,
  • PKCS5Padding 填充方式:为JAVA的默认填充方式,对加密数据字节长度对8取余为r,如r大于0,则补8-r个字节,字节为8-r的值;如果r等于0,则补8个字节8。比如:加密字符串为为AAA,则补位为AAA55555;加密字符串为BBBBBB,则补位为BBBBBB22;加密字符串为CCCCCCCC,则补位为CCCCCCCC88888888。

DES —— 消息传递过程

  • 甲方(发送者)生成密钥Key
  • 将生成的key传给乙方
  • 甲方使用密钥对字符串进行加密
  • 甲方加加密后的字符串传给乙方
  • 乙方根据密钥key对字符串进行解密操作

DES和DESEde —— 简介

DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。需要注意的是,在某些文献中,作为算法的DES称为数据加密算法(Data Encryption Algorithm,DEA),已与作为标准的DES区分开来。

1988年后,实例化DES算法破译机的出现,彻底宣告DES算法已经不具备安全性。

3DES(即Triple DES)是DES向AES过渡的加密算法,它使用3条56位的密钥对数据进行三次加密。是DES的一个更安全的变形。它以DES为基本模块,通过组合分组方法设计出分组加密算法。比起最初的DES,3DES更为安全。

DESEde使用两个密钥,执行三次DES算法,加密的过程是加密-解密-加密,解密的过程是解密-加密-解密

  • 3DES加密过程为:C=Ek3(Dk2(Ek1(P)))
  • 3DES解密过程为:P=Dk1(EK2(Dk3(C)))

采用两个密钥进行三重加密的好处有:

  1. 两个密钥合起来有效密钥长度有112bit,可以满足商业应用的需要,若采用总长为168bit的三个密钥,会产生不必要的开销。
  2. 加密时采用加密-解密-加密,而不是加密-加密-加密的形式,这样有效的实现了与现有DES系统的向后兼容问题。因为当K1=K2时,三重DES的效果就和原来的DES一样,有助于逐渐推广三重DES。
  3. 三重DES具有足够的安全性,目前还没有关于攻破3DES的报道。

密匙比较:

DES密匙:   be+SuW5Jnc0=
DESEde密匙:JrkV4N/TXRlkZHP3Aj1h38TCitlRvz1R

从密匙长度我们可以看出三重DES的缺点就是解密的速度会比DES慢很多,时间换安全也是非常值得的事情。

DES —— 算法实现

DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位(实际用到了56位,第8、16、24、32、40、48、56、64位是校验位, 使得每个密钥都有奇数个1),其算法主要分为两步:

1.) 初始置换

其功能是把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位,其置换规则为将输入的第58位换到第一位,第50位换到第2位……依此类推,最后一位是原来的第7位。L0、R0则是换位输出后的两部分,L0是输出的左32位,R0是右32位,例:设置换前的输入值为D1D2D3……D64,则经过初始置换后的结果为:L0=D58D50……D8;R0=D57D49……D7。

其置换规则见下表:
58,50,42,34,26,18,10,2,
60,52,44,36,28,20,12,4,
62,54,46,38,30,22,14,6,
64,56,48,40,32,24,16,8,
57,49,41,33,25,17,9,1,
59,51,43,35,27,19,11,3,
61,53,45,37,29,21,13,5,
63,55,47,39,31,23,15,7,

2.) 逆置换

经过16次迭代运算后,得到L16、R16,将此作为输入,进行逆置换,逆置换正好是初始置换的逆运算,由此即得到密文输出

转载请注明:R&M » DES —— 数据加密标准

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

联系我:rm@rmworking.com