【问题标题】:BitShifting with BigIntegers in Java在 Java 中使用 BigIntegers 进行位移
【发布时间】:2010-04-28 05:20:15
【问题描述】:

我正在使用 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: 1111000111100110011010101010000000000000000000000

c12: 111101010101001100110000111100000000000000000000000

d12: 111100011110011001101010101000000000000000000000000

c13: 11110101010100110011000011110000000000000000000000000

d13: 11110001111001100110101010100000000000000000000000000

c14: 1111010101010011001100001111000000000000000000000000000

d14: 1111000111100110011010101010000000000000000000000000000

c15: 11110101010100110011000011110000000000000000000000000000

d15: 11110001111001100110101010100000000000000000000000000000

【问题讨论】:

    标签: java encryption key biginteger des


    【解决方案1】:

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

    【讨论】:

    • 这不是精度有限吗?如果bi 有 100 位呢?
    • 是的,精度有限。但是,c0 是 29 位,c15 是 56,所以我假设用户想要一些小于 64 的精度。检查 Wiki 中的 DES 算法,我看到 28 位的一半在该算法中被旋转,所以我更新了我的回答。谢谢。
    【解决方案2】:

    看来你需要一个循环左移。 BigInteger.shiftLeft 不是循环的。您必须组合 shiftLeftshiftRightandor,就像使用 int&lt;&lt; 时一样。

    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)来优化它,而不是每次都计算它。

    【讨论】:

    • 不,这不起作用,因为他发布的原因是:无限精度的 BigInteger 将继续向右添加 0。你的算法需要一个 and(BigInteger.valueOf(0xffffffffL).
    • 不,算法仍然不适用于任意精度的整数,因为它们需要设置高位。例如,对 BigInteger.valueOf(1) 重复应用 cyclicLeftShift 总是返回 1,这肯定不是有意的。对不起,但这次投反对票。修复允许用户传入 L,我将删除。
    • @bkail:我承认我不了解应用程序(DES?),但那是我想要的。我现在意识到固定周期窗口可能是 OP 需要的,所以我在回答中澄清了这一点。感谢您的反馈。
    • 删除了反对票。我相信他正在实施这个:en.wikipedia.org/wiki/Data_Encryption_Standard
    【解决方案3】:

    解决更大的问题 1) DES 已损坏,除了与遗留系统一起工作外,不得用于任何其他用途,2) Sun JCE 已经提供了一个实现(就像 BouncyCastle 和其他加密提供者一样),以及 3) 实现任何加密算法具有挑战性,您真的希望使用经过良好测试的实现来用于生产。

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2022-01-05
        • 2017-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多