在 Java 中使用 DES 实现返回的密文不正确
Incorrect returned cipher text with DES Implementation in Java
对于一个小任务,我被要求在不使用 Java 中已有的预定义函数的情况下实现 DES 算法。我让它工作了,但是返回的加密文本不正确。它 returns 6C 17 96 35 BE 47 EF 95 当它应该是 AA 39 B9 77 7E FC 3C 14. 有什么想法我哪里出错了吗?
跟进; 3 月 8 日
按照 David Koontz 的建议使用 this manual 他将我链接到了。我相信加密在子密钥生成过程中开始出错。
跟进; 3 月 8 日晚些时候
我很生气地检查了我的代码的每一步,我发现了问题所在。在我的一个 for 循环中,我使用了 int j=0;我<16; i++ 而不是使用 j。愚蠢的错误,但也没有人发现它哦。已在发布的代码中更正。
package des.implementation;
import java.nio.ByteBuffer;
public class DESImplementation {
private static final byte[] IP = {
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
};
private static final byte[] FP = {
40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25
};
private static final byte[] E = {
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1
};
private static final byte[][] S = { {
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
}, {
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
}, {
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
}, {
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
}, {
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
}, {
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
}, {
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
}, {
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
} };
private static final byte[] P = {
16, 7, 20, 21,
29, 12, 28, 17,
1, 15, 23, 26,
5, 18, 31, 10,
2, 8, 24, 14,
32, 27, 3, 9,
19, 13, 30, 6,
22, 11, 4, 25
};
private static final byte[] PC1 = {
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4
};
private static final byte[] PC2 = {
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
};
private static final byte[] rotations = {
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
private static int charToNibble(char c) {
if (c>='0' && c<='9') {
return (c-'0');
} else if (c>='a' && c<='f') {
return (10+c-'a');
} else if (c>='A' && c<='F') {
return (10+c-'A');
} else {
return 0;
}
}
private static byte[] parseBytes(String s) {
s = s.replace(" ", "");
byte[] ba = new byte[s.length()/2];
if (s.length()%2 > 0) { s = s+'0'; }
for (int i=0; i<s.length(); i+=2) {
ba[i/2] = (byte) (charToNibble(s.charAt(i))<<4 | charToNibble(s.charAt(i+1)));
}
return ba;
}
private static long permute(byte[] table, int srcWidth, long src) {
long dst = 0;
for (int i=0; i<table.length; i++) {
int srcPos = srcWidth - table[i];
dst = (dst<<1) | (src>>>srcPos & 0x01);
}
return dst;
}
private static byte[] longToBytes(long x) {
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
buffer.putLong(x);
return buffer.array();
}
private static byte S(int boxNumber, byte src) {
src = (byte) (src&0x20 | ((src&0x01)<<4) | ((src&0x1E)>>>1));
return S[boxNumber-1][src];
}
private static int P(int src) { return (int)permute(P, 32, src&0xFFFFFFFFL); }
private static int feistel(int r, long subkey) {
long e = permute(E, 32, r&0xFFFFFFFFL);
long x = e ^ subkey;
int dst = 0;
for (int i=0; i<8; i++) {
dst>>>=4;
int s = S(8-i, (byte)(x&0x3F));
dst |= s << 28;
x>>>=6;
}
return P(dst);
}
private static long bytesToLong(byte[] bytes) {
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
buffer.put(bytes);
buffer.flip();
return buffer.getLong();
}
public static void main(String[] args) {
byte[] message = parseBytes("0123456789ABCDEF");
byte[] key = parseBytes("3b3898371520f75e");
byte[] ciphertext = new byte[message.length];
for(int i=0; i<message.length; i+=8){
long Lmessage = bytesToLong(message);
long Lkey = bytesToLong(key);
long subkeys[] = new long[16];
Lkey = permute(PC1, 64, Lkey);
int c = (int) (Lkey>>>28);
int d = (int) (Lkey&0x0FFFFFFF);
for (int j=0; j<16; j++) { //the problem was found here
if (rotations[j] == 1) {
c = ((c<<1) & 0x0FFFFFFF) | (c>>>27);
d = ((d<<1) & 0x0FFFFFFF) | (d>>>27);
} else {
c = ((c<<2) & 0x0FFFFFFF) | (c>>>26);
d = ((d<<2) & 0x0FFFFFFF) | (d>>>26);
}
long cd = (c&0xFFFFFFFFL)<<28 | (d&0xFFFFFFFFL);
subkeys[j] = permute(PC2, 56, cd);
}
long ip = permute(IP, 64, Lmessage);
int l = (int) (ip>>>32);
int r = (int) (ip&0xFFFFFFFFL);
for (int k=0; k<16; k++) {
int previous_l = l;
l = r;
r = previous_l^feistel(r, subkeys[k]);
}
long rl = (r&0xFFFFFFFFL)<<32 | (l&0xFFFFFFFFL);
long fp = permute(FP, 64, rl);
ciphertext = longToBytes(fp);
}
StringBuilder Message = new StringBuilder();
StringBuilder Key = new StringBuilder();
StringBuilder Cipher = new StringBuilder();
for (int i=0; i<ciphertext.length; i++) {
Message.append(String.format("%02X ",message[i]));
Key.append(String.format("%02X ",key[i]));
Cipher.append(String.format("%02X ",ciphertext[i]));
}
System.out.println("Message: "+Message.toString());
System.out.println("Key: "+Key.toString());
System.out.println("Cipher: "+Cipher.toString());
}
}
在检查我的代码的每一步后,我发现了问题所在。在我的一个 for 循环中,我使用了 int j=0;我<16; i++ 而不是使用 j。愚蠢的错误,但也没有人发现它哦。已在发布的代码中更正。
对于一个小任务,我被要求在不使用 Java 中已有的预定义函数的情况下实现 DES 算法。我让它工作了,但是返回的加密文本不正确。它 returns 6C 17 96 35 BE 47 EF 95 当它应该是 AA 39 B9 77 7E FC 3C 14. 有什么想法我哪里出错了吗?
跟进; 3 月 8 日
按照 David Koontz 的建议使用 this manual 他将我链接到了。我相信加密在子密钥生成过程中开始出错。
跟进; 3 月 8 日晚些时候
我很生气地检查了我的代码的每一步,我发现了问题所在。在我的一个 for 循环中,我使用了 int j=0;我<16; i++ 而不是使用 j。愚蠢的错误,但也没有人发现它哦。已在发布的代码中更正。
package des.implementation;
import java.nio.ByteBuffer;
public class DESImplementation {
private static final byte[] IP = {
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
};
private static final byte[] FP = {
40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25
};
private static final byte[] E = {
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1
};
private static final byte[][] S = { {
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
}, {
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
}, {
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
}, {
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
}, {
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
}, {
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
}, {
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
}, {
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
} };
private static final byte[] P = {
16, 7, 20, 21,
29, 12, 28, 17,
1, 15, 23, 26,
5, 18, 31, 10,
2, 8, 24, 14,
32, 27, 3, 9,
19, 13, 30, 6,
22, 11, 4, 25
};
private static final byte[] PC1 = {
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4
};
private static final byte[] PC2 = {
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
};
private static final byte[] rotations = {
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
private static int charToNibble(char c) {
if (c>='0' && c<='9') {
return (c-'0');
} else if (c>='a' && c<='f') {
return (10+c-'a');
} else if (c>='A' && c<='F') {
return (10+c-'A');
} else {
return 0;
}
}
private static byte[] parseBytes(String s) {
s = s.replace(" ", "");
byte[] ba = new byte[s.length()/2];
if (s.length()%2 > 0) { s = s+'0'; }
for (int i=0; i<s.length(); i+=2) {
ba[i/2] = (byte) (charToNibble(s.charAt(i))<<4 | charToNibble(s.charAt(i+1)));
}
return ba;
}
private static long permute(byte[] table, int srcWidth, long src) {
long dst = 0;
for (int i=0; i<table.length; i++) {
int srcPos = srcWidth - table[i];
dst = (dst<<1) | (src>>>srcPos & 0x01);
}
return dst;
}
private static byte[] longToBytes(long x) {
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
buffer.putLong(x);
return buffer.array();
}
private static byte S(int boxNumber, byte src) {
src = (byte) (src&0x20 | ((src&0x01)<<4) | ((src&0x1E)>>>1));
return S[boxNumber-1][src];
}
private static int P(int src) { return (int)permute(P, 32, src&0xFFFFFFFFL); }
private static int feistel(int r, long subkey) {
long e = permute(E, 32, r&0xFFFFFFFFL);
long x = e ^ subkey;
int dst = 0;
for (int i=0; i<8; i++) {
dst>>>=4;
int s = S(8-i, (byte)(x&0x3F));
dst |= s << 28;
x>>>=6;
}
return P(dst);
}
private static long bytesToLong(byte[] bytes) {
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
buffer.put(bytes);
buffer.flip();
return buffer.getLong();
}
public static void main(String[] args) {
byte[] message = parseBytes("0123456789ABCDEF");
byte[] key = parseBytes("3b3898371520f75e");
byte[] ciphertext = new byte[message.length];
for(int i=0; i<message.length; i+=8){
long Lmessage = bytesToLong(message);
long Lkey = bytesToLong(key);
long subkeys[] = new long[16];
Lkey = permute(PC1, 64, Lkey);
int c = (int) (Lkey>>>28);
int d = (int) (Lkey&0x0FFFFFFF);
for (int j=0; j<16; j++) { //the problem was found here
if (rotations[j] == 1) {
c = ((c<<1) & 0x0FFFFFFF) | (c>>>27);
d = ((d<<1) & 0x0FFFFFFF) | (d>>>27);
} else {
c = ((c<<2) & 0x0FFFFFFF) | (c>>>26);
d = ((d<<2) & 0x0FFFFFFF) | (d>>>26);
}
long cd = (c&0xFFFFFFFFL)<<28 | (d&0xFFFFFFFFL);
subkeys[j] = permute(PC2, 56, cd);
}
long ip = permute(IP, 64, Lmessage);
int l = (int) (ip>>>32);
int r = (int) (ip&0xFFFFFFFFL);
for (int k=0; k<16; k++) {
int previous_l = l;
l = r;
r = previous_l^feistel(r, subkeys[k]);
}
long rl = (r&0xFFFFFFFFL)<<32 | (l&0xFFFFFFFFL);
long fp = permute(FP, 64, rl);
ciphertext = longToBytes(fp);
}
StringBuilder Message = new StringBuilder();
StringBuilder Key = new StringBuilder();
StringBuilder Cipher = new StringBuilder();
for (int i=0; i<ciphertext.length; i++) {
Message.append(String.format("%02X ",message[i]));
Key.append(String.format("%02X ",key[i]));
Cipher.append(String.format("%02X ",ciphertext[i]));
}
System.out.println("Message: "+Message.toString());
System.out.println("Key: "+Key.toString());
System.out.println("Cipher: "+Cipher.toString());
}
}
在检查我的代码的每一步后,我发现了问题所在。在我的一个 for 循环中,我使用了 int j=0;我<16; i++ 而不是使用 j。愚蠢的错误,但也没有人发现它哦。已在发布的代码中更正。