在Java或C中对字符进行位操作?

时间:2011-08-05 16:37:26

标签: java c bit-manipulation bit des

我是一名试图实施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 个答案:

答案 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();
        }
    }