简体   繁体   English

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

[英]recasting a unsigned char array to an unsigned long array

Ok, I'm using a raw SHA1 hash to seed a Mersenne Twister pseudo-random number generator the generator gives me the option to seed either with an unsigned long or a array of unsigned longs 好吧,我正在使用原始SHA1哈希来播种Mersenne Twister伪随机数生成器,生成器为我提供了使用无符号长整数或无符号长整数数组播种的选项

the SHA1 class I'm using gives me the hash as a 20 byte array of unsigned chars 我正在使用的SHA1类将哈希值作为20字节的无符号字符数组

I figured I could recast this array of chars to an array of longs to get a working seed but how can I know how long the resulting array of longs is? 我想我可以将这个字符数组重新组合成一个长数组来获得一个有效的种子,但我怎么知道得到的long数组有多长?

example code: 示例代码:

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

I'm hoping that there is no data loss (as in no bytes are dropped off) as I need this to remain cryptography secure 我希望没有数据丢失(因为没有字节被丢弃),因为我需要保持加密安全

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

You can say 你可以说

sizeof(unsigned long) / sizeof(unsigned char)

to get the number of octets in a long. 获得长的八位字节数。

However there are two potential problems with simply casting. 然而,简单铸造有两个潜在的问题。

First, the array of chars might not be properly aligned. 首先,字符数组可能没有正确对齐。 On some processors this can cause a trap. 在某些处理器上,这会导致陷阱。 On others it just slows execution. 在其他方面,它只会减慢执行速度。

Second, you're asking for byte order problems if the program must work the same way on different architecutures. 其次,如果程序必须在不同的架构上以相同的方式工作,那么您就会要求字节顺序问题。

You can solve both problems by copying the bytes into an array of longs explicitly. 您可以通过将字节显式复制到long数组来解决这两个问题。 Untested code: 未经测试的代码:

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.

Your library seems to assume 32-bit unsigned long s, so there's no [more] harm in you doing the same. 你的库似乎假定32位unsigned long s,所以你做同样的事情没有[更多]伤害。 In fact, I'd go as far to assume 8-bit unsigned char s and perhaps even unpadded, little-endian representations for both. 实际上,我会尽可能地假设8位unsigned char ,甚至可能是两个未填充的小端表示。 So you could use a simple cast (though I'd use a reinterpret_cast ), or maybe @Gene's memcpy sample for alignment. 所以你可以使用一个简单的强制转换(尽管我使用reinterpret_cast ),或者@ Gene的memcpy样本用于对齐。

Portable code*, however, should use <cstdint> , the uint#_t types therein and piecewise, by-value copying for conversion: 但是,可移植代码*应该使用<cstdint> ,其中的uint#_t类型和分段,按值复制进行转换:

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

...and better names. ......还有更好的名字。 Sorry, it's getting late here :) 对不起,这里来得晚了:)

*: Though, of course, stdint itself isn't very portable (>= C++11) and the exact-width types aren't guaranteed to be in it. *:当然,虽然stdint 本身不是非常便携(> = C ++ 11),并且不能保证精确宽度类型。 Ironic. 具有讽刺意味的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM