1、初始置换(IP置换):将输入的64位明文块进行置换和重新排列,生成新的64位数据块。
2、加密轮次:DES加密算法共有16个轮次,每个轮次都包括四个步骤:
a. 将64位数据块分为左右两个32位块。
b. 右侧32位块作为输入,经过扩展、异或、置换等操作生成一个48位的数据块。这个48位的数据块被称为“轮密钥”,它是根据加密算法的主密钥生成的子密钥。
c. 将左侧32位块和轮密钥进行异或运算,结果作为新的右侧32位块。
d. 将右侧32位块与原来的左侧32位块进行连接,生成一个新的64位数据块,作为下一轮的输入。
3 末置换(FP置换):在最后一个轮次完成后,将经过加密的数据块进行置换和重新排列,得到加密后的64位密文。
DES 解密实现方法与问题解决方案
DES(Data Encryption Standard)是一种对称加密算法,其解密过程与加密过程相似,但使用子密钥的顺序相反。DES 的解密实现主要包括以下几个关键步骤:
初始置换(Initial Permutation, IP)
DES 解密的第一步是对密文进行初始置换,其置换方式与加密时的初始置换相同。该步骤将 64 位密文按照固定置换表重新排列,为后续的 Feistel 结构处理做准备。
16 轮 Feistel 解密结构
DES 的核心是 16 轮的 Feistel 结构,解密过程中每一轮使用的子密钥顺序与加密时相反。具体来说,第 1 轮使用加密时的第 16 个子密钥,第 2 轮使用第 15 个子密钥,依此类推,直到第 16 轮使用第 1 个子密钥。每一轮的处理包括扩展置换、异或操作、S 盒替换和 P 盒置换等步骤。
S 盒替换与 P 盒置换
S 盒(Substitution Box)是 DES 中实现非线性变换的关键组件,用于将 6 位输入转换为 4 位输出。P 盒(Permutation Box)则用于重新排列数据位,以增强扩散效果。在解密过程中,S 盒和 P 盒的使用方式与加密过程相同。
逆初始置换(Inverse Initial Permutation, IP⁻¹)
经过 16 轮 Feistel 处理后,输出的 64 位数据进行逆初始置换,最终得到明文。
在实现 DES 解密时,需要注意以下几个关键问题:
密钥调度问题
DES 使用 64 位密钥(其中 8 位为奇偶校验位),实际有效密钥长度为 56 位。在解密时,必须确保子密钥的生成顺序与加密时相反,否则无法正确恢复明文。
ALGORITHM参数:指定核心算法名称
作用:标识使用的加密算法类型,固定为三重DES(Triple DES)。
常见值:
DESede(Java/CryptoJS等)
TripleDES(.NET等)
底层原理:
该参数告知加密库使用3DES的底层实现,包括:
密钥结构:生成或解析24字节密钥(K1、K2、K3),支持168位(三密钥)或112位(双密钥,K1=K3)模式。
基础操作:执行三次DES运算(加密-解密-加密,即EDE流程)
TRANSFORMATION参数:定义具体执行规则
作用:细化算法的工作模式和填充方式,格式为:算法/模式/填充。
工作模式(Mode):
ECB(电子密码本):每个数据块独立加密,相同明文生成相同密文,安全性低,适用于短数据。
CBC(密码分组链接):每个块与前一块密文异或后再加密,需初始化向量(IV),安全性更高。
其他模式:CFB、OFB等流模式(较少使用)。
填充方式(Padding):
PKCS5Padding / PKCS7Padding:缺位补N字节,每字节值为N(如缺3字节补0x03 0x03 0x03)。
NoPadding:要求明文长度是8字节(64位)的整数倍,否则报错
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class TripleDESDemo {
private static final String ALGORITHM = "DESede";
private static final String TRANSFORMATION = "DESede/ECB/PKCS5Padding";
public static byte[] encrypt(byte[] plaintext, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return cipher.doFinal(plaintext);
}
public static byte[] decrypt(byte[] ciphertext, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return cipher.doFinal(ciphertext);
}
public static void main(String[] args) throws Exception {
String message = "hello 3des";
String keyStr = "12312312312312312312312312312312"; // 32 字符,对应 168 位密钥
byte[] key = keyStr.getBytes();
byte[] encrypted = encrypt(message.getBytes(), key);
byte[] decrypted = decrypt(encrypted, key);
System.out.println("Original: " + message);
System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encrypted));
System.out.println("Decrypted: " + new String(decrypted));
}
}