之前我们介绍了《「后端」加密算法之 HMAC 算法》,今天我们认识 DES 算法。
从今天开始我们介绍加密算法中的对称加密算法。相信大家看了前几篇文章,已经对摘要算法的使用已经有了比较深的认识,摘要算法由于其算法特性,只能单向加密,无法对数据反向解密,这时对称加密算法就出现了。对称算法主要有 DES、3DES 和 AES,今天我们重点介绍一下对称加密算法中的 DES 算法。
DES 算法介绍
DES (Data Encryption Standard) 算法是世界上最常用的加密算法。在很长时间内,许多人心目中“密码生成”与DES一直是个同义词。尽管后来有个叫 Electronic Frontier Foundation的组织造了台价值 22 万的机器尝试破解 DES 加密的数据,直到现在 DES 和它的变种 3DES(三重数据加密算法)仍然在政府和银行中被广泛使用。
注:在 2001 年A ES 算法成为了 DES 算法的替代品。
国家标准局催生了 DES
1973 年 5 月,在尼克松任期,美国国家标准局下发了红头文件,征求加密算法来保护传输过程中的数据。国家标准局等了很久一直没有人投标,一直到 1974 年 8 月 6 日,尼克松卸任前三天,IBM 才拿出了自己家开发的一套代号 LUCIFER(金星)的东西。美国安全局评估后,在 1977 年 7 月 15 日采用了 LUCIFER 的一个变种作为数据加密标准 DES。
DES 很快被非数字媒体采用,比如电话线中的信号加密。在那些年里,国际香料组织 IFF 曾用 DES 来加密那些用电话线传输的秘密配方。("With Data Encryption, Scents Are Safe at IFF," Computerworld 14, No. 21, 95 (1980))
同时,作为政府之后第二大急需加密的银行业也将 DES 作为广泛应用的标准,美国国家标准协会 ANSI 制定了整个银行业的加密规范。1980 年采用的 ANSI X3.92 指定了 DES 算法的应用。
DES 算法特点
- DES 加密算法属于对称加密,加密与解密用的是同一个密钥。
- DES 加密算法要求密钥必须是 8 个字节,即 64bit 长度;有效秘钥长度为 56 位,每个字节第 8 位用作奇偶校验。
- 因为密钥是 byte[8],代表字符串也可以是非可见的字节,可以与 Base64 编码算法一起使用。
- 加密、解密都需要通过字节数组作为数据和密钥进行处理。
- DES 算法是两种加密技术的组合:混乱和扩散。先替代后置换。
- 易于实现,DES 算法只是使用了标准的算术和逻辑运算,其作用的数最多也只有 64 位,因此用 70 年代末期的硬件技术很容易实现。
DES 算法的优缺点
优点:
- 效率高,算法简单,系统开销小
- 适合加密大量数据
- 明文长度和密文长度相等
缺点:
- 需要以安全方式进行秘钥交换
- 秘钥管理复杂
DES 算法具有很高的安全性,到目前为止,除了用穷举搜索法对 DES 算法进行攻击外,还没有发现更有效的办法。而 56 位长的密钥的穷举空间为 256,这意味着如果一台计算机的速度是每一秒种检测一百万个密钥,则它搜索完全部密钥就需要将近 2285 年的时间,可见,这是难以实现的,当然,随著科学技术的发展,当出现超高速计算机后,我们可考虑把DES 密钥的长度再增长一些,以此来达到更高的保密程度。
DES 加密原理
DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半。使用子密钥对其中一半应用循环功能,然后将输出与另一半进行"异或"运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES 使用 16 个循环,使用异或,置换,代换,移位操作四种基本运算。
DES 的加密过程
- 64 位密钥经子密钥产生算法产生出 16 个 48 位子密钥:K1,K2,...,K16,分别供第 1 次,第 2 次,...,第 16 次加密迭代使用。
- 64 位明文首先经过初始置换 IP,将数据打乱重新排列并分成左右两半,左边 32 位构成L0,右边 32 位构成 R0。
- 第 i 次加密迭代:由轮函数f实现子密钥 Ki 对 Ri-1 的加密,结果为 32 位的数据组 f ( Ri-1 , Ki )。f ( Ri-1 , Ki ) 再与 Li-1 模 2 相加,又得到一个 32 位的数据组 Li-1 ⊕ f ( Ri-1 , Ki )。以 Li ⊕ f ( Ri-1 , Ki ) 作为下一次加密迭代的 Ri,以 Ri-1 作为下一次加密迭代的 Li ( i = 1,2,...,16)。
- 按照上一步的规则进行 16 次加密迭代。
- 第 16 次加密迭代结束后,以R 16 为左,L16 为右,合并产生一个 64 位的数据组。再经过逆初始置换I P-1,将数据重新排列,便得到 64 位密文。
DES 的解密过程
- 64 位密钥经子密钥产生算法产生出 16 个 48 位子密钥:K1,K2,...,K16,分别供第 1 次,第 2 次,...,第 16 次解密迭代使用。
- 64 位密文首先经过初始置换 IP,将数据打乱重新排列并分成左右两半,左边 32 位构成R16,右边 32 位构成 L16。
- 第 17-i 次解密迭代:由轮函数 f 实现子密钥 Ki 对 Li 的解密,结果为 32 位的数据组 f ( Li , Ki )。f ( Li , Ki ) 再与 Ri 模 2 相加,又得到一个 32 位的数据组 Ri ⊕ f ( Li , Ki )。以 Ri ⊕ f ( Li , Ki ) 作为下一次解密迭代的 Li-1,以 Li 作为下一次解密迭代的 Li-1 ( i = 16,15,...,1)。
- 按照上一步的规则进行 16 次解密迭代。
- 第 16 次解密迭代结束后,以 L0 为左,R0 为右,合并产生一个 64 位的数据组。再经过逆初始置换 IP-1,将数据重新排列,便得到 64 位明文。
DES 算法实现
对称加密算法会有不同的分组模式和填充方式,这里我们使用的分组模式是 ECB,填充模式为 NoPadding,目前这种方式是比较常见的应用场景,实现代码示例如下:
private static final String DES_ALGORITHM = "DES";
private static final String DES_CIPHER = "DES/ECB/NoPadding";
// des 加密
public static byte[] encryptDES(String data, String key) throws Exception {
// 生成SecretKey对象
SecretKey secretKey = desKeyGenerator(key);
// Cipher对象实际完成加密操作
Cipher cipher = Cipher.getInstance(DES_CIPHER);
// 用密匙初始化Cipher对象
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
// 执行加密操作
return cipher.doFinal(data.getBytes());
}
// des 解密
public static byte[] decryptDES(byte[] data, String key) throws Exception {
// 生成SecretKey对象
SecretKey secretKey = desKeyGenerator(key);
// Cipher对象实际完成解密操作
Cipher cipher = Cipher.getInstance(DES_CIPHER);
// 用密匙初始化Cipher对象
cipher.init(Cipher.DECRYPT_MODE, secretKey);
// 执行解密操作
return cipher.doFinal(data);
}
/**
* DES Key 生成方法
*
* @param key
* @return
*/
private static SecretKey desKeyGenerator(String key) {
try {
// 创建一个DESKeySpec对象
DESKeySpec desKey = new DESKeySpec(key.getBytes());
// 创建一个密匙工厂
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_ALGORITHM);
// 将DESKeySpec对象转换成SecretKey对象
return keyFactory.generateSecret(desKey);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return null;
}
/**
* Nopadding填充时,明文不是8位的倍数时需补足,这里补位0x00
*
* @param b
* @return
*/
private static byte[] fillZero(byte[] b) {
int len = b.length;
//data不足8位以0补足8位
if (b.length % 8 != 0) {
len = b.length - b.length % 8 + 8;
} else {
return b;
}
byte[] needData = null;
needData = new byte[len];
for (int i = 0; i < len; i++) {
needData[i] = 0x00;
}
System.arraycopy(b, 0, needData, 0, b.length);
return needData;
}
应用场景
DES 算法最常用的场景是银行业,如银行卡收单,信用卡持卡人的 PIN 的加密传输,IC 卡 与 POS 间的双向认证、金融交易数据包的 MAC 校验等,均用到 DES 算法。另外,在 POS、ATM、磁卡及智能卡(IC 卡)、加油站、高速公路收费站等领域,DES 算法也被广泛应用,以此来实现关键数据的保密。
总结
上面介绍了一下 DES 算法的和 DES 的实现,3DES 算法是 DES 的变种,并不是一种新的算法,这里就不做过多介绍了,实现方式可以去下载完整源码查看。关于对称加密算法我们还没有完整的讨论对称加密中的分组模式以及填充模式,虽然代码实现中也涉及了分组和填充,下一节我们会详细介绍这部分内容。
DES 算法虽然有被破解的可能,但是目前依然在一些金融系统中被广泛使用,尤其工作是在金融方面的小伙伴们,也是需要大家去了解和掌握的,以便于工作中遇到时可以有的放矢。
文章来源:https://zhuanlan.zhihu.com/p/345835990