【问题标题】:16 byte unsigned char array as a number?16字节无符号字符数组作为数字?
【发布时间】:2018-07-30 05:35:43
【问题描述】:

我正在使用 128 位密钥进行一些加密,这需要使用 16 字节数据块,我将其存储为 16 字节无符号字符数组。

unsigned char nonce_counter[16] = "xCv6Jk0neeV5GoSZ";

我经常需要将值视为一个数字来进行一些数学运算,但我似乎找不到一种安全的方法来对值进行类型转换。

如何将 16 字节的值转换为数值数据类型?

具体来说,我需要使用按位异或 A^B 并递增 A++

我知道我可以做显而易见的事情并使用 for 循环并独立处理数组的每个元素,但我担心这样做会降低效率。

我的系统不支持__uint128_t

【问题讨论】:

  • 您忘记提问了吗?
  • @JacobG。我不小心在我打算之前提交并在我这样做后立即开始编辑,但感谢您的提醒。
  • 如果您有一个兼容的 int128_t 并且数组中的字节顺序实际上与您的系统架构的字节序匹配,这是可能的。否则,您可能会发现迭代字节或一次可能两个或四个字节的速度一样快,具体取决于字节序。
  • 假设您实际上有一个 16 字节的 int 值,但您会遇到字节序问题...
  • 您的应用程序是否对这种效率水平敏感?您多久对此类号码执行一次此类处理?

标签: c arrays encryption casting type-conversion


【解决方案1】:

如果您使用 gcc,您可以使用 __uint128_t 指针并通过它修改数组:

unsigned char nonce_counter[16] = "xCv6Jk0neeV5GoSZ";
__uint128_t* A = (__uint128_t*)nonce_counter;

*A += 1;
*A ^= *B;

【讨论】:

  • 查看我对字节序的评论。这不仅仅是关于编译器对 128 位整数的支持。
  • XOR 操作是可移植的并且是有意义的,另一方面,增量会在不同的架构上产生不同的结果。
  • __uint128_t* A = (__uint128_t*)nonce_counter; 会导致对齐问题。考虑union
  • @mdatsev 遗憾的是我的系统不支持 __uint128_t 但仍然感谢您的帮助。
【解决方案2】:

如何将 16 字节的值转换为数值数据类型?
我的系统不支持 __uint128_t。

如果编译器不支持128位类型,那么就没有数值数据类型的解决方案。


一个有用的替代方法是union

避免将字符数组指针转换为更宽整数的指针。它可能会导致对齐错误(总线故障)。

对于这种类型的应用程序,使用uint8_t 而不是unsigned char 更清楚。

#include <stdint.h>
typedef union {
  uint8_t u8[16];
  uint64_t u64[2];
} my_uint128;

像下面这样的代码需要解决字节序问题。

void foo() {
  my_uint128 nonce_counter = { .u8 =  "xCv6Jk0neeV5GoSZ"};
  btoh_128(&nonce_counter); // this would be a no-op on a BE machine
  ...

^ 是字节序安全的。

inline my_uint128 xor_128(my_uint128 a, my_uint128 b) {
  return (my_uint128) { .u64[0] = a.u64[0] ^ b.u64[0], .u64[1] = a.u64[1] ^ b.u64[1]};
}

增量需要更多的工作。 LSB_128 根据字节序定义为 0 或 1。

inline my_uint128 inc_128(my_uint128 a) {
  if (++a.u64[LS_128] == 0) { 
    ++a.u64[MS_128]
  }
  return a;
}

我担心这样做会降低效率。

在放弃此方法之前尝试上述方法并验证效率损失。给你的编译器一个优化的机会。


uint64_t u64[2];LS_128 的替代方案是 struct { uint64_t ms,ls; };ls, ms 按照平台的字节序排序。


这种方法的一个优点是union 可以包含uint128_t 成员(如果支持)。然后各种例程可以直接使用 128 位数学而不更改调用代码。

【讨论】:

  • 我们甚至不知道 OP 是否有 64 位整数可用。
  • @jwdonahue re: if the OP has 64 bit integers 没错,但自 C99 以来所有兼容的 C 编译器都具有至少 64 位的 unsigned long long。所以没有太多的假设。
  • 实际上,对于嵌入式系统来说,这可能是一个巨大的飞跃。 OP 在某处提到了在网络芯片上运行代码。
  • @jwdonahue 我所做的嵌入式工作支持 64 位类型,即使使用 16 位处理器和适度的编译器。所以OP,(lancegerday)你使用的是什么编译器?
  • 是的,这就是为什么我问他们有什么能力。
猜你喜欢
  • 1970-01-01
  • 2018-05-25
  • 1970-01-01
  • 1970-01-01
  • 2013-07-11
  • 2018-04-07
  • 1970-01-01
  • 2020-07-17
  • 2017-12-03
相关资源
最近更新 更多