7

我正在使用 BigIntegers 在 Java 中实现 DES 加密。

通过执行 BigInteger.leftShift(int n) 方法,我使用 Java BigIntegers 左移二进制键。N(Kn)的键取决于Kn-1移位的结果。我遇到的问题是,我在生成每个密钥后打印出结果,并且移位不是预期的输出。密钥分为 2 个 Cn 和 Dn(分别为左和右)。

我特别尝试这样做:“要进行左移,请将每个位向左移动一个位置,但第一位除外,它循环到块的末尾。”

根据班次,它似乎在最后加上 O。不知道如何去纠正这个。

结果:

c0: 11110101010100110011000011110

d0: 11110001111001100110101010100

c1: 111101010101001100110000111100

d1: 111100011110011001101010101000

c2: 11110101010100110011000011110000

d2: 11110001111001100110101010100000

c3: 1111010101010011001100001111000000

d3: 1111000111100110011010101010000000

c4: 111101010101001100110000111100000000

d4: 111100011110011001101010101000000000

c5: 11110101010100110011000011110000000000

d5: 11110001111001100110101010100000000000

c6: 1111010101010011001100001111000000000000

d6: 1111000111100110011010101010000000000000

c7: 111101010101001100110000111100000000000000

d7: 111100011110011001101010101000000000000000

c8: 1111010101010011001100001111000000000000000

d8: 1111000111100110011010101010000000000000000

c9: 111101010101001100110000111100000000000000000

d9: 111100011110011001101010101000000000000000000

c10: 11110101010100110011000011110000000000000000000

d10: 11110001111001100110101010100000000000000000000

c11: 1111010101010011001100001111000000000000000000000

d11: 11110001111001100110101010100000000000000000000000

c12: 111101010101001100110000111100000000000000000000000

d12: 111100011110011001101010101000000000000000000000000

c13: 11110101010100110011000011110000000000000000000000000

d13: 11110001111001100110101010100000000000000000000000000

c14: 1111010101010011001100001111000000000000000000000000000

d14: 1111000111100110011010101010000000000000000000000000000

c15: 11110101010100110011000011110000000000000000000000000000

d15: 11110001111001100110101010100000000000000000000000000000

4

4 回答 4

10

BigInteger 实现了无限精度整数,因此向左移动将不断向左侧添加零。你需要一个旋转:

private static BigInteger rotateLeft(BigInteger bi) {
    BigInteger ret = bi.shiftLeft(1);
    if (ret.testBit(32)) {
        ret = ret.clearBit(32).setBit(0);
    }
    return ret;
}

对于 32 位数字,这将是相当低效的,因此您不妨只使用原语来旋转 DES 的 28 位一半。我不熟悉 DES 算法,所以我假设您需要 BigInteger 来做其他事情。

private static BigInteger rotateLeftPrimitive(BigInteger bi) {
    int value = bi.intValue();
    return BigInteger.valueOf(((value << 1) & 0xffffffe) | ((value >>> 27) & 1));
}
于 2010-04-28T05:35:22.600 回答
4

看来您需要循环左移。BigInteger.shiftLeft不是循环的。您必须组合shiftLeft,和shiftRight,就像使用and一样。andorint<<

static BigInteger allOnes(int L) {
    return BigInteger.ZERO
        .setBit(L)
        .subtract(BigInteger.ONE);
}

static BigInteger cyclicLeftShift(BigInteger n, int L, int k) {
    return n.shiftLeft(k)
        .or(n.shiftRight(L - k))
        .and(allOnes(L));
}

现在,cyclicLeftShift(n, L, k)n循环移位k的位返回到左侧,循环窗口为L

它的工作原理如下:

                               _________L__________
                              /                    \
n :                           [ABCDE][FG...........]
                              \__k__/\_____L-k_____/



n.shiftLeft(k) :       [ABCDE][FG...........][00000]
   .or
n.shiftRight(L - k) :                        [ABCDE]

   =                   [ABCDE][FG...........][ABCDE]

                               _________L__________
   .and                       /                    \
allOnes(L) :                  [111..............111]

   =                          [FG...........][ABCDE]

也可以看看


注意:如果你有一个固定的L,你可以通过缓存allOnes(L)而不是每次都计算来优化它。

于 2010-04-28T05:31:48.660 回答
1

解决更大的问题 1) DES 已损坏,除了与遗留系统一起使用外,不应用于任何其他用途,2) Sun JCE 已经提供了实现(BouncyCastle 和其他加密提供者也是如此),以及 3) 实现任何加密算法都是具有挑战性,并且您真的想使用经过良好测试的实现以供生产使用。

如果是课堂练习,我会使用 byte[] 而不是 BigInteger。您需要手动做更多的事情,但它更接近 DES 的精神,因为它被设计为易于在硬件中实现。

于 2010-04-28T17:00:46.210 回答
0

我认为您使用位字符串实现 DES 的想法作为一种教育工具是合理的。与其直接使用 BigIntegers 来表示这些位串,我建议您创建一个 BitString 类,该类准确地实现您项目所需的位串方法。在 BitString 类中,您可以使用 BigIntegers,但您可能会发现每个数组元素 1 位的简单 int 数组同样容易或更容易,或者可能是链表。

于 2010-04-29T01:19:02.463 回答