按位运算的类型转换使我在C中感到困惑

时间:2017-07-04 10:25:57

标签: c char int bit-manipulation unsigned

我正在尝试加密加密。我正试图用我得到的密钥流来加密数据。

数据的格式为uint8_t,密钥流KS为uint32_t。

变量n是数据的长度(显然是32位块)

我有这段代码:

for (i=0; i<n; i++)
{
  wo_data[4*i+0] ^= (uint8_t)(KS[i] >> 24) & 0xff;
  wo_data[4*i+1] ^= (uint8_t)(KS[i] >> 16) & 0xff;
  wo_data[4*i+2] ^= (uint8_t)(KS[i] >>  8) & 0xff;
  wo_data[4*i+3] ^= (uint8_t)(KS[i]      ) & 0xff;
}

但它甚至没有达到预期效果。

现在,如果我输入数据为32位长度:

uint32_t* data2 = (uint32_t *)wo_data;
for(i=0; i < n; i++)
{
  data2[i] ^= KS[i];
}

它开始起作用了。有人能解释一下为什么吗?我宁愿使用8位长度,因为如果输入数据不是字节对齐的话,更容易对齐结尾。

数据初始化如下:

7EC61272 743BF161 4726446A 6C38CED1
66F6CA76 EB543004 4286346C EF130F92

KS初始化如下:

F22DB45B 37E71C5B 4EB6F404 CD886C15
9DCA27B1 F062AF46 F8E2F587 8976E8B8

我期待着(显然):

8CEBA629 43DCED3A 0990B06E A1B0A2C4
FB3CEDC7 1B369F42 BA64C1EB 6665E72A

1 个答案:

答案 0 :(得分:3)

正如@Arkku在评论中所说,这是一个字节序问题。

例如,如果您使用的是小端机器,则以下列方式存储K [0] = 0xF22DB45B:

@K+0: 5B
@K+1: B4
@K+2: 2D
@K+3: F2

因此,每个KS字的最低有效字节(LSB)必须与wo_data[4*i+0]进行异或,依此类推。

此代码给出了预期值:

for (int i=0; i < N; i++)
{
    wo_data[4*i+0] ^= ((KS[i]      ) & 0xff);
    wo_data[4*i+1] ^= ((KS[i] >>  8) & 0xff);
    wo_data[4*i+2] ^= ((KS[i] >> 16) & 0xff);
    wo_data[4*i+3] ^= ((KS[i] >> 24) & 0xff);
}

32位版本可能更快,因为它每个指令处理更多字节。而且,它可以以更有效的方式进行矢量化和执行。请参阅generated assembly for the 8- and 32-bit versions。如果有的话,8位版本可用于处理剩余的字节。