在 java 中将 4 位推入一个 int
Push 4 bits into an int in java
为了实现 SPN 加密功能(相关研究),我试图将 4 位推入一个 int。
我可以查明错误,但我不知道如何修复它(现在可能盯着它看了太久)。
private int applySBox(int a, boolean inverse, boolean verbose) {
// split int (16 bit) into parts of 4 bit keeping the right order
int[] parts = new int[4];
for(int i = 0; i < 4; i++) {
parts[4 - i - 1] = a & 0b1111;
a = a >> 4;
}
// Apply the SBox to each 4 bit
// E.g. 1101 traverse (enc) = 1001, inverse (dec) = 0010
for(int i = 0; i < 4; i++) {
if(inverse) {
parts[i] = sbox.inverse(parts[i]);
} else {
parts[i] = sbox.traverse(parts[i]);
}
}
int result = 0;
// put back together
for(int i = 0; i < 4; i++) {
result = parts[i] & 0b1111;
// TODO: Reassigning does not help here, needs shift and &
result = result << 4;
}
return result;
}
在 SBox 之前,我可能会得到 1100111011001111
的值作为密文。
在分割部分我得到这样的东西:
Fragment[0]: 0001100011110000
Round Value: 0001100011110000
Current key: 1101011000111111
New r Value: 1100111011001111
---
Before SBox: 1100_1110_1100_1111
Part[0] before SBox: 1100
Part[1] before SBox: 1110
Part[2] before SBox: 1100
Part[3] before SBox: 1111
Part[0] after SBox: 1011
Part[1] after SBox: 0000
Part[2] after SBox: 1011
Part[3] after SBox: 0101
根据我必须使用的 SBox 的定义,我知道这是正确的。
这意味着,为了得到结果,我必须将部分 0 到 3 pack 推入一个 int 1011_0000_1011_0101
,这将是正确的结果。
我可以清楚地看到它不起作用,因为我总是用 result = parts[i] & 0b1111;
覆盖结果我似乎找不到修复方法。
如何将一个 int[] 数组按从 0 到 3 的顺序将每个具有 4 位数据的 int 推送到包含 16 位数据的 int 结果中?
你的意思是:
result = (result << 4) | parts[i];
或者,同样的事情写法不同:
result |= parts[i] << (4 * (4-i));
如果是这样,那么,是的,你盯着屏幕看的时间太长了,就像他们说的那样“眼睛圆了”!
更新:因为 OP 暗示可以 lock-in 四个部分。这是 traverse
变体的未经测试的 one-liner:
return sbox.traverse(a & 0b1111)
| sbox.traverse(a >> 4 & 0b1111) << 4
| sbox.traverse(a >> 8 & 0b1111) << 8
| sbox.traverse(a >> 12 & 0b1111) << 12
如果将位向左移动,则最右边的位将填满零。因此,您需要对结果进行 XOR 或 OR。
尝试更换
result = parts[i] & 0b1111;
与
result ^= parts[i] & 0b1111;
或
result |= parts[i] & 0b1111;
否则你只是重新分配值并删除前面的 4 位块。
为了实现 SPN 加密功能(相关研究),我试图将 4 位推入一个 int。
我可以查明错误,但我不知道如何修复它(现在可能盯着它看了太久)。
private int applySBox(int a, boolean inverse, boolean verbose) {
// split int (16 bit) into parts of 4 bit keeping the right order
int[] parts = new int[4];
for(int i = 0; i < 4; i++) {
parts[4 - i - 1] = a & 0b1111;
a = a >> 4;
}
// Apply the SBox to each 4 bit
// E.g. 1101 traverse (enc) = 1001, inverse (dec) = 0010
for(int i = 0; i < 4; i++) {
if(inverse) {
parts[i] = sbox.inverse(parts[i]);
} else {
parts[i] = sbox.traverse(parts[i]);
}
}
int result = 0;
// put back together
for(int i = 0; i < 4; i++) {
result = parts[i] & 0b1111;
// TODO: Reassigning does not help here, needs shift and &
result = result << 4;
}
return result;
}
在 SBox 之前,我可能会得到 1100111011001111
的值作为密文。
在分割部分我得到这样的东西:
Fragment[0]: 0001100011110000
Round Value: 0001100011110000
Current key: 1101011000111111
New r Value: 1100111011001111
---
Before SBox: 1100_1110_1100_1111
Part[0] before SBox: 1100
Part[1] before SBox: 1110
Part[2] before SBox: 1100
Part[3] before SBox: 1111
Part[0] after SBox: 1011
Part[1] after SBox: 0000
Part[2] after SBox: 1011
Part[3] after SBox: 0101
根据我必须使用的 SBox 的定义,我知道这是正确的。
这意味着,为了得到结果,我必须将部分 0 到 3 pack 推入一个 int 1011_0000_1011_0101
,这将是正确的结果。
我可以清楚地看到它不起作用,因为我总是用 result = parts[i] & 0b1111;
覆盖结果我似乎找不到修复方法。
如何将一个 int[] 数组按从 0 到 3 的顺序将每个具有 4 位数据的 int 推送到包含 16 位数据的 int 结果中?
你的意思是:
result = (result << 4) | parts[i];
或者,同样的事情写法不同:
result |= parts[i] << (4 * (4-i));
如果是这样,那么,是的,你盯着屏幕看的时间太长了,就像他们说的那样“眼睛圆了”!
更新:因为 OP 暗示可以 lock-in 四个部分。这是 traverse
变体的未经测试的 one-liner:
return sbox.traverse(a & 0b1111)
| sbox.traverse(a >> 4 & 0b1111) << 4
| sbox.traverse(a >> 8 & 0b1111) << 8
| sbox.traverse(a >> 12 & 0b1111) << 12
如果将位向左移动,则最右边的位将填满零。因此,您需要对结果进行 XOR 或 OR。
尝试更换
result = parts[i] & 0b1111;
与
result ^= parts[i] & 0b1111;
或
result |= parts[i] & 0b1111;
否则你只是重新分配值并删除前面的 4 位块。