我是一名试图实施DES算法的学生。 我有两种语言可供选择:C& Java的。 我确实理解了这个算法,但是在操作密钥时一开始就陷入困境。
这是问题所在。
在DES中,我们有一个64位密钥(C中有8个字符,Java中有4个字符,但我可以将字符串转换为字节以仅获取ASCII部分),其中每8位是一个奇偶校验位,需要被剥离使其成为56位密钥并进行进一步处理。我已经考虑了很久了,但找不到剥离每个第8位的方法并将结果存储在另一个char数组中(在Java和C中)。
我尝试使用java.util.BitSet class
,但感到困惑。
有关如何删除每个第8位并连接相邻字节(Java)或字符(C)以获取56位密钥的任何建议?
我知道位操作和移位,但是对于具体的例子:
假设我有一个16位密钥:1100 1001 1101 1000
我需要删除第8位和第16位,然后输入密钥:1100 100 1101 100
。
如果我声明2个字节,我如何截断第8位并将第9位附加到它,使第一个字节成为:1100 1001
那么,我需要帮助的是如何将第8位替换为第9位,将第16位替换为第17位,依此类推从64位密钥导出56位密钥?
如果有人可以向我解释,我可能无论语言如何都可以实现它。
答案 0 :(得分:3)
小心Java中的16位字符。许多方法仅转换低8位。仔细阅读文档。由于打字比C更强,因此将加密密钥视为Java中的byte[]
更为常见。
关于奇偶校验位,请仔细检查DES算法并查看它们的使用位置。这应该会给你一个关于你需要做什么的提示。
答案 1 :(得分:1)
在C中,您可以使用按位运算符(例如&
和|
)以及bitshift运算符<<
和>>
来操作位。
例如,要关闭给定字节的高位,可以执行此操作。
char c = 0xBF; // initial value is bit pattern 10111111
c &= 0x7F; // perform AND against the bit pattern 01111111
// final value is bit pattern 00111111 (0x3F)
这有意义吗? 显然,你需要能够从位模式转换为十六进制,但这并不太难。
您可以使用类似的屏蔽来提取所需的位,并将它们放在输出缓冲区中。
<强>更新强>
您有64位(8字节)输入,并且需要56位(7字节)输出。
让我们将您的输入表示为以下内容,其中每个字母代表一个位 'x'位是你要丢弃的位。
xAAAAAAA xBBBBBBB xCCCCCCC xDDDDDDD xEEEEEEE xFFFFFFF xGGGGGGG xHHHHHHH
所以你希望你的最终答案是:
AAAAAAAB BBBBBBCC CCCCCDDD DDDDEEEE EEEFFFFF FFGGGGGG GHHHHHHH
所以在C中,我们可能会有这样的代码:
unsigned char data[8] = {/* put data here */};
// chop off the top bit of the first byte
data[0] <<= 1;
// the bottom bit of data[0] needs to come from the top data bit of data[1]
data[0] |= (data[1] >> 6) & 0x01;
// use similar transformations to fill in data[1], data[2], ... data[6]
// At the end, data[7] will be useless
当然,这根本没有优化,但希望你能得到这个想法。
答案 2 :(得分:0)
我可以简单介绍一下......如果需要,我会进一步解释......
将所有8个字符右移1,即c1 = c1&gt;&gt; 1等
Multiplyc1与总字节数(即56)即c1 * 0x0000000000(不确定多少个零)
然后,将0x0000 +添加到下一个字符,即c2 = c2 + 0x0000; c3 = c3 + 0x000000等等(继续为继续的字符添加2 0)
现在,开始添加c1 + c2 + c3 .......
这里的想法是,首先用零填写数字并开始添加其他字符,以便它们保持正确躺着
00 00 00 00 00 00 00 00 00
34 00 00 00 00 00 00 00 00 (c1 = c1>>1) . Here c1=0x34, c2=0x67
00 67 00 00 00 00 00 00 00 (c2 = c2>>1)
so on...............
在上面添加; 我希望这会有所帮助。
答案 3 :(得分:0)
@jwd,@ jscode 非常感谢你的帮助。 jwd:我从你的代码中得到了这个想法。我读完之后看起来非常简单的逻辑.. :-)不知道为什么我没想到这一点。 好吧,我做了一点点改进你的想法,现在在Java中工作正常。 如果有人有任何建议,请告诉我。 谢谢.. P.S。:测试部分非常原始。我打印位值。我手动完成了几个例子并使用相同的输入,它工作正常。
=============================================
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter an 8 char key: ");
String input;
try {
// get key, key.length()>=8 chars
input = br.readLine();
if (input.length() < 8) {
System.out.println("Key < 8B. Exiting. . .");
System.exit(1);
}
// java char has 16 bits instead of 8 bits as in C,
// so convert it to 8 bit char by getting lower order byte &
// discarding higher order byte
char[] inputKey = input.toCharArray();
byte[] key64 = new byte[8];
byte[] key56 = new byte[7];
// consider only first 8 chars even if input > 8
for (int counter = 0; counter < 8; counter++)
key64[counter] = (byte) inputKey[counter];
System.out.print("\n$$ " + new String(key64) + " $$\n");
// converting 64bit key to 56 bit key
for (int counter = 0; counter < KEY_LENGTH - 1; counter++) {
key64[counter] = (byte) (key64[counter] >>> 1);
key64[counter] = (byte) (key64[counter] << 1);
}
for (int counter = 0; counter < KEY_LENGTH - 1; counter++) {
key56[counter] = (byte) (key64[counter] << counter);
key56[counter] = (byte) (key56[counter] | (key64[counter + 1] >>> (KEY_LENGTH - 1 - counter)));
}
/*Conversion from 64 to 56 bit testing code
System.out.println(new String(key56));
System.out.println();
for (int counter1 = 0; counter1 < 7; counter1++) {
for (int counter2 = 7; counter2 >= 0; counter2--) {
System.out.println(key56[counter1] & (1 << counter2));
}
System.out.println();
}*/
} catch (IOException e) {
e.printStackTrace();
}
}