在 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 位块。