3

我是一名试图实现 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 位密钥?

如果有人可以向我解释,我可能能够实现它,而不管语言如何。

4

4 回答 4

3

注意 Java 中的 16 位字符。许多方法只转换低 8 位。仔细阅读文档。在 Java中将加密密钥视为 aa 更为常见,byte[]因为其类型比在 C 中更强。

至于奇偶校验位,请仔细检查 DES 算法,看看它们在哪里使用。这应该给你一个关于你需要对它们做什么的提示。

于 2011-08-05T16:45:57.697 回答
1

在 C 中,您可以使用按位运算符操作位,例如&and |,以及位移运算符<<and >>

例如,要关闭给定字节的高位,您可以这样做。

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

当然,这根本没有优化,但希望你明白这一点。

于 2011-08-05T16:44:35.690 回答
0

我可以简要介绍一种方法....如果需要,我将进一步解释...

将所有 8 个字符右移 1 即 c1 = c1>>1 等

将 c1 与总字节数(即 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...............

在上面添加;我希望这将有所帮助。

于 2011-08-05T20:08:32.653 回答
0

@jwd,@jscode 非常感谢您的帮助。致 jwd:我从你的代码中得到了这个想法。在我阅读之后似乎很简单的逻辑.. :-) 想知道为什么我没有想到这一点。好吧,我确实稍微完善了你的想法,现在它在 Java 中运行良好。如果有人有任何建议,请告诉我。谢谢.. PS:测试部分非常原始。我打印位值。我为几个示例手动完成了它,并使用与输入相同的方法,它工作正常。

==============================================

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();
        }
    }
于 2011-08-07T11:00:27.617 回答