将unsigned char数组重建为unsigned long数组

时间:2012-10-23 01:44:15

标签: c++ casting sha1 mersenne-twister

好的,我正在使用原始SHA1哈希来播种Mersenne Twister伪随机数生成器 生成器为我提供了使用无符号长整数或无符号长整数数组种子的选项

我正在使用的SHA1类将哈希值作为20字节的无符号字符数组

我想我可以将这个字符数组重新组合成一个long数组以获得一个有效的种子,但是我怎么知道得到的long数组有多长?

示例代码:

CSHA1 sha1;
sha1.Update((unsigned char*)key, size_key);
sha1.Final();
unsigned char* hash;
sha1.GetHash(hash);

// Seed the random with the key
MTRand mt((unsigned long*)hash, <size of array of longs>);

我希望没有数据丢失(因为没有字节被丢弃),因为我需要保持加密安全

3 个答案:

答案 0 :(得分:1)

您可以使用len_of_chars * sizeof(char) / sizeof(long),其中len_of_chars大概是20。

答案 1 :(得分:1)

你可以说

sizeof(unsigned long) / sizeof(unsigned char)

获取长的八位字节数。

然而,简单铸造有两个潜在的问题。

首先,字符数组可能没有正确对齐。在某些处理器上,这会导致陷阱。在其他方面,它只会减慢执行速度。

其次,如果程序必须在不同的架构上以相同的方式工作,那么你就会要求字节顺序问题。

您可以通过将字节显式复制到long数组来解决这两个问题。未经测试的代码:

const int bytes_per_long = sizeof(unsigned long) / sizeof(unsigned char);
unsigned long hash_copy[key_length_in_bytes / bytes_per_long];
int i_hash = 0;
for (int i_copy = 0; i_copy < sizeof hash_copy / sizeof hash_copy[0]; i_copy++) {
  unsigned long b = 0;
  for (int i_byte = 0; i_byte < bytes_per_long; i_byte++)
    b = (b << 8) | hash[i_hash++];
  hash_copy[i_copy] = b;
}
// Now use hash_copy.

答案 2 :(得分:0)

Your library似乎假定32位unsigned long s,所以你做同样的事情没有[更多]伤害。实际上,我会尽可能地假设8位unsigned char s,甚至可能是两个未填充的小端表示。所以你可以使用一个简单的强制转换(尽管我使用reinterpret_cast),或者@ Gene的memcpy样本进行对齐。

然而,便携式代码*应使用<cstdint>,其中uint#_t类型以及分段,按值复制进行转换:

uint32_t littleEndianInt8sToInt32(uint8_t bytes[4]) {
    return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
}

......还有更好的名字。对不起,现在已经很晚了:))

*:当然,stdint 本身不是非常便携(&gt; = C ++ 11),并且不能保证精确宽度类型它。具有讽刺意味的。