一、算法原理概述
参考自老师的PPT
加密过程
初始置换IP
迭代T
Feistel轮函数
子秘钥生成
逆置换IP-1
解密过程
二、总体结构
class DES{
//构造函数
public DES(StringBuffer text, StringBuffer key, int mode) throws Exception {
}
//PKCS5填充处理明文
public StringBuffer dealText(final StringBuffer origin) {
}
//初始置换IP
public void start() {
//把明文或者密文转换成二进制字符串
//分组加密或解密
IP(...);
}
//IP置换
public void IP(final String plaintextBinary) {
//通过IP置换明文
//把置换后的明文分为左右两块
iterationT(...);
}
//迭代T
public void iterationT(StringBuffer L, StringBuffer R) {
//得到子秘钥
getSbuKey(...);
//16次迭代
feistel(...);
//左右交换
//逆置换
//生成字符串明文或密文
//END!
}
//Feistel轮函数
public StringBuffer feistel(final StringBuffer R, final StringBuffer subKey ) {
//E扩展
//异或运算
//S-Box
//P置换
}
//子秘钥生成
public StringBuffer[] getSubKey() {
//把key转换为二进制
//PC1置换
// LS循环16轮生成子密钥
// 把左右两块合并
// PC2置换
// 根据PC2压缩C0D0,得到子密钥
}
//主函数
public static void main(String[] args){
start();}
}
三、模块分解
PKCS5填充处理明文
public StringBuffer dealText(final StringBuffer origin) {
StringBuffer textBinary = new StringBuffer();
//使用PKCS#5/PKCS7填充
int max = group*8;
int padding = max - origin.length();
for (int i = 0; i < max; ++i) {
StringBuffer charBinary;
if(i >= origin.length()) {
charBinary = new StringBuffer(Integer.toBinaryString(padding));
}else
charBinary = new StringBuffer(Integer.toBinaryString(origin.charAt(i)));
while (charBinary.length() < 8) {
charBinary.insert(0, 0);
}
textBinary.append(charBinary);
}
return textBinary;
}
字符串转二进制
public StringBuffer string2Binary(final StringBuffer origin) {
StringBuffer textBinary = new StringBuffer();
for (int i = 0; i < origin.length(); ++i) {
StringBuffer charBinary = new StringBuffer(Integer.toBinaryString(origin.charAt(i)));
while (charBinary.length() < 8) {
charBinary.insert(0, 0);
}
textBinary.append(charBinary);
}
return textBinary;
}
IP置换
public void IP(final String plaintextBinary) {
//通过IP置换明文
StringBuffer substitutePlaintext = new StringBuffer(); // 存储置换后的明文
for (int i = 0; i < 64; ++i) {
substitutePlaintext.append(plaintextBinary.charAt(IP[i] - 1));
}
//把置换后的明文分为左右两块
StringBuffer L = new StringBuffer(substitutePlaintext.substring(0, 32));
StringBuffer R = new StringBuffer(substitutePlaintext.substring(32));
iterationT(L, R);
}
Feistel轮函数
public StringBuffer feistel(final StringBuffer R, final StringBuffer subKey ) {
//E扩展
StringBuffer RExtent = new StringBuffer(); // 存储扩展后的右边
for (int i = 0; i < 48; ++i) {
RExtent.append(R.charAt(E[i] - 1));
}
//异或运算
for (int i = 0; i < 48; ++i) {
RExtent.replace(i, i + 1, (RExtent.charAt(i) == subKey.charAt(i)) ? "0" :"1");
}
//S-Box
StringBuffer SBoxString = new StringBuffer();
for(int i = 0; i < 8; ++i) {
String SBoxInput = RExtent.substring(i * 6, (i + 1) * 6);
int row = Integer.parseInt(Character.toString(SBoxInput.charAt(0)) + SBoxInput.charAt(5), 2);
int column = Integer.parseInt(SBoxInput.substring(1, 5), 2);
StringBuffer SBoxOutput = new StringBuffer(Integer.toBinaryString(SBox[i][row * 16 + column]));
while (SBoxOutput.length() < 4) {
SBoxOutput.insert(0, 0);
}
SBoxString.append(SBoxOutput);
}
//P置换
StringBuffer substituteSBoxString= new StringBuffer(); // 存储置换后的R
for (int i = 0; i < 32; ++i) {
substituteSBoxString.append(SBoxString.charAt(P[i] - 1));
}
return substituteSBoxString;
}
子密钥生成
//子秘钥生成
public StringBuffer[] getSubKey() {
//把key转换为二进制
StringBuffer keyBinary = string2Binary(key);
StringBuffer[] subKey = new StringBuffer[16]; // 存储子密钥
//PC1置换
StringBuffer C0 = new StringBuffer(); // 存储密钥左块
StringBuffer D0 = new StringBuffer(); // 存储密钥右块
for (int i = 0; i < 28; ++i) {
C0.append(keyBinary.charAt(PC1[i] - 1));
D0.append(keyBinary.charAt(PC1[i + 28] - 1));
}
// LS循环16轮生成子密钥
for (int i = 0; i < 16; ++i) {
// 循环左移
char mTemp;
mTemp = C0.charAt(0);
C0.deleteCharAt(0);
C0.append(mTemp);
mTemp = D0.charAt(0);
D0.deleteCharAt(0);
D0.append(mTemp);
if(i != 0 && i != 1 && i != 8 && i != 15) {
mTemp = C0.charAt(0);
C0.deleteCharAt(0);
C0.append(mTemp);
mTemp = D0.charAt(0);
D0.deleteCharAt(0);
D0.append(mTemp);
}
// 把左右两块合并
StringBuffer C0D0 = new StringBuffer(C0.toString() + D0.toString());
// PC2置换
// 根据PC2压缩C0D0,得到子密钥
StringBuffer C0D0Temp = new StringBuffer();
for (int j = 0; j < 48; ++j) {
C0D0Temp.append(C0D0.charAt(PC2[j] - 1)