0

好的,我正在使用原始 SHA1 散列来播种 Mersenne Twister 伪随机数生成器,生成器让我可以选择使用 unsigned long 或 unsigned long 数组播种

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

我想我可以将这个 chars 数组重铸为 longs 数组以获得工作种子,但我怎么知道得到的 longs 数组有多长?

示例代码:

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>);

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

4

3 回答 3

1

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

于 2012-10-23T01:47:54.437 回答
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.
于 2012-10-23T02:00:34.423 回答
0

您的库似乎假定 32-bit unsigned longs,因此您这样做没有 [更多] 危害。事实上,我会尽可能假设 8 位unsigned chars 甚至可能是未填充的小端表示。因此,您可以使用简单的演员表(尽管我会使用 a 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 它本身不是很便携(>= C++11),并且不能保证精确宽度类型在其中。讽刺。

于 2012-10-23T02:33:55.623 回答