【问题标题】:Bit manipulation of chars in Java or C?Java或C中的字符位操作?
【发布时间】:2011-08-05 16:37:25
【问题描述】:

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

如果有人可以向我解释它,我也许可以不分语言地实现它。

【问题讨论】:

  • 不清楚你所说的“and I 4 in Java”是什么意思。

标签: java c bit-manipulation bit des


【解决方案1】:

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

至于奇偶校验位,请仔细检查 DES 算法并查看它们的使用位置。这应该会提示您需要对它们做什么。

【讨论】:

    【解决方案2】:

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

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

    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
    

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

    【讨论】:

      【解决方案3】:

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

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

      将 c1 与总字节数 (ie56) 相乘,即 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...............
      

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

      【讨论】:

      • 如果您还在寻找解决方案,请告诉我...但是我只能在 C 中提供解决方案。
      【解决方案4】:

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

      【讨论】:

      • 我很确定 DES 的第一步已经完成 - 通过删除每 8 位将 64 位密钥转换为 56 位密钥..!!
      猜你喜欢
      • 2020-05-26
      • 2016-06-22
      • 2016-04-18
      • 2017-06-06
      • 1970-01-01
      • 2014-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多