I am implementing DES Encryption in Java with use of BigIntegers.
I am left shifting binary keys with Java BigIntegers by doing the BigInteger.leftShift(int n) method. Key of N (Kn) is dependent on the result of the shift of Kn-1. The problem I am getting is that I am printing out the results after each key is generated and the shifting is not the expected out put. The key is split in 2 Cn and Dn (left and right respectively).
I am specifically attempting this: "To do a left shift, move each bit one place to the left, except for the first bit, which is cycled to the end of the block. "
It seems to tack on O's on the end depending on the shift. Not sure how to go about correcting this.
Results:
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
BigInteger implements infinite-precision integers, so shifting to the left will keep adding zeros to the left. You need a rotate:
private static BigInteger rotateLeft(BigInteger bi) {
BigInteger ret = bi.shiftLeft(1);
if (ret.testBit(32)) {
ret = ret.clearBit(32).setBit(0);
}
return ret;
}
That's going to be rather inefficient for 32-bit numbers, so you might as well just use primitives to rotate DES' 28-bit halves. I'm not familiar with the DES algorithm, so I'll assume you need BigInteger for something else.
private static BigInteger rotateLeftPrimitive(BigInteger bi) {
int value = bi.intValue();
return BigInteger.valueOf(((value << 1) & 0xffffffe) | ((value >>> 27) & 1));
}
It seems that you need a cyclic left shift. BigInteger.shiftLeft
is not cyclic. You'd have to combine shiftLeft
, shiftRight
, and
and or
, just like you would if you were using int
and <<
.
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));
}
Now, cyclicLeftShift(n, L, k)
returns n
cyclically-shifted k
bits to the left, where the cycle window is L
.
How this works is as follows:
_________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]
Note: if you have a fixed L
, you can optimize this a bit by caching allOnes(L)
instead of computing it every time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With