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)))
采用两个密钥进行三重加密的好处有:
- 两个密钥合起来有效密钥长度有112bit,可以满足商业应用的需要,若采用总长为168bit的三个密钥,会产生不必要的开销。
- 加密时采用加密-解密-加密,而不是加密-加密-加密的形式,这样有效的实现了与现有DES系统的向后兼容问题。因为当K1=K2时,三重DES的效果就和原来的DES一样,有助于逐渐推广三重DES。
- 三重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,将此作为输入,进行逆置换,逆置换正好是初始置换的逆运算,由此即得到密文输出
--Posted from Rpc