我正在使用BigIntegers在Java中实现DES加密。
我通过执行BigInteger.leftShift(int n)方法将Java二进制密钥与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:111100011110011001101010101000000000000000000000000000000
c14:1111010101010011001100001111000000000000000000000000000
d14:11110001111001100110101010100000000000000000000000000000000
c15:11110101010100110011000011110000000000000000000000000000
d15:111100011110011001101010101000000000000000000000000000000000
答案 0 :(得分: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));
}
答案 1 :(得分:4)
您似乎需要循环左移。 BigInteger.shiftLeft
不是循环的。您必须将shiftLeft
,shiftRight
,and
和or
合并,就像使用int
和<<
一样。
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)
来优化这一点,而不是每次都计算它。
答案 2 :(得分:1)
解决更大的问题1)DES被破坏,除了使用遗留系统之外不应该用于其他任何事情,2)Sun JCE已经提供了一个实现(如BouncyCastle和其他加密提供者),以及3)实现任何加密算法具有挑战性,您真的希望采用经过良好测试的生产用途。
如果是课堂练习,我会使用byte []而不是BigInteger。你需要手工做更多的事情,但它更接近DES的精神,因为它的设计很容易在硬件中实现。
答案 3 :(得分:0)
我认为您使用位串实现DES的想法作为一种教育工具是合理的。我建议您创建一个BitString类,而不是直接使用BigIntegers来表示这些位串,而是实现项目所需的那些位串方法。在BitString类中,您可以使用BigIntegers,但您可能会发现每个数组元素为1位的简单int数组同样简单或容易,或者可能是链表。