如何基于给定S盒实现eLeftQ位运算处理unsigned char数组?
问题
已知如下S盒:
const unsigned char sbox[16][16] = { {0x5, 0xC, 0x1, 0x0, 0x2, 0xE, 0x9, 0x8, 0xF, 0xD, 0x3, 0xB, 0x7, 0xA, 0x4, 0x6}, {0xF, 0x4, 0x3, 0xA, 0x8, 0xD, 0x6, 0x2, 0x5, 0xE, 0x1, 0x7, 0xB, 0x0, 0xC, 0x9}, {0x6, 0x7, 0xD, 0x2, 0x0, 0x3, 0xF, 0xA, 0x9, 0x1, 0xE, 0x4, 0xC, 0x8, 0xB, 0x5}, {0x8, 0xD, 0x7, 0x9, 0xF, 0x4, 0x0, 0x5, 0x2, 0xC, 0xB, 0x3, 0x1, 0x6, 0xE, 0xA}, {0x4, 0xF, 0x0, 0x1, 0xD, 0x8, 0x7, 0xE, 0xC, 0x2, 0xA, 0x6, 0x9, 0x3, 0x5, 0xB}, {0x9, 0xB, 0xE, 0x8, 0xA, 0x1, 0x5, 0x0, 0x6, 0x3, 0xD, 0xC, 0x4, 0x2, 0x7, 0xF}, {0xA, 0x1, 0xC, 0xF, 0x9, 0xB, 0x2, 0x6, 0x0, 0x7, 0x4, 0xE, 0xD, 0x5, 0x3, 0x8}, {0xE, 0x2, 0x9, 0x7, 0xC, 0x5, 0x1, 0x4, 0xD, 0xF, 0x6, 0xA, 0x0, 0xB, 0x8, 0x3}, {0x7, 0x6, 0x8, 0xE, 0x3, 0x0, 0x4, 0x1, 0xB, 0xA, 0x2, 0xF, 0x5, 0xD, 0x9, 0xC}, {0x2, 0xE, 0xB, 0x6, 0x5, 0xC, 0xA, 0xF, 0x8, 0x4, 0x7, 0x1, 0x3, 0x9, 0xD, 0x0}, {0xB, 0x9, 0x2, 0xD, 0x1, 0xA, 0xC, 0x3, 0x7, 0x0, 0x8, 0x5, 0xF, 0xE, 0x6, 0x4}, {0x0, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x1, 0x2}, {0x3, 0x0, 0xF, 0xC, 0x7, 0x6, 0xD, 0xB, 0x1, 0x9, 0x5, 0x8, 0x2, 0x4, 0xA, 0xE}, {0x1, 0xA, 0x5, 0x4, 0xB, 0x9, 0xE, 0x7, 0x3, 0x6, 0xF, 0x2, 0x8, 0xC, 0x0, 0xD}, {0xD, 0x8, 0x6, 0xB, 0x4, 0xF, 0x3, 0xC, 0xE, 0x5, 0x9, 0x0, 0xA, 0x7, 0x2, 0x1}, {0xC, 0x5, 0xA, 0x3, 0xE, 0x2, 0xB, 0xD, 0x4, 0x8, 0x0, 0x9, 0x6, 0x1, 0xF, 0x7}, };
需要实现eLeftQ运算,定义如下:
eLeft(Q,∗)l : Q^n → Q^n, a_0,...,a(n-1) → b_0,...,b_(n-1), b_0 = l ∗ a_0, b_i = b_(i−1) ∗ a_i, i = 1,...,n
其中*运算由上述S盒定义:x * y = sbox[x][y],例如0x5 * 0xF = sbox[5][15] = 0xF,0xF * 0x5 = sbox[15][5] = 0x2。
当前需求:处理unsigned char数组,每个元素为8位,需按高4位→低4位的顺序,将每个4位作为运算单元,执行eLeftQ规则计算后替换原4位。示例流程:
- 初始值L=0xF(二进制1111),数组为
{0xA2, 0x85}(对应二进制1010 0010、1000 0101) - 步骤1:取第一个char的高4位0xA(10),计算
sbox[0xF][0xA] = 0x0,替换后该char变为0x02(0000 0010) - 步骤2:取该char的低4位0x2(2),计算
sbox[0x0][0x2] = 0x1,替换后该char变为0x01(0000 0001) - 步骤3:取第二个char的高4位0x8(8),计算
sbox[0x1][0x8]得到结果,替换后更新该char。
原思路是提取4位转int计算后写回,但觉得低效且实现麻烦,求更优方案。
优化实现方案
直接用位操作结合unsigned char的特性处理,无需额外类型转换,效率高且代码简洁。核心逻辑是:遍历数组每个字节,依次处理高4位和低4位,用当前状态值(初始为L)和提取的4位值直接索引S盒,得到结果后写回对应位,同时更新状态值。
代码实现
void eLeftQ_process(unsigned char* arr, size_t arr_len, unsigned char initial_L) { unsigned char current_state = initial_L; for (size_t i = 0; i < arr_len; ++i) { unsigned char byte = arr[i]; // 处理高4位 unsigned char high_nibble = (byte >> 4) & 0x0F; unsigned char new_high = sbox[current_state][high_nibble]; byte = (byte & 0x0F) | (new_high << 4); current_state = new_high; // 处理低4位 unsigned char low_nibble = byte & 0x0F; unsigned char new_low = sbox[current_state][low_nibble]; byte = (byte & 0xF0) | new_low; current_state = new_low; arr[i] = byte; } }
关键优化点
- 无多余类型转换:所有操作均使用
unsigned char完成,4位值范围0-15刚好匹配S盒索引,无需转int。 - 直接位操作:
- 提取高4位:
(byte >> 4) & 0x0F,右移4位后保留低4位; - 提取低4位:
byte & 0x0F; - 写回高4位:
(byte & 0x0F) | (new_high << 4),保留原低4位,替换高4位; - 写回低4位:
(byte & 0xF0) | new_low,保留原高4位,替换低4位。
- 提取高4位:
- 状态链式更新:每处理完一个4位单元,立即将结果更新为下一次运算的状态值,完全符合eLeftQ的链式运算规则。
内容的提问来源于stack exchange,提问作者wxist
相关产品推荐
相关产品推荐

