преобразование массива без знака в длинный массив без знака

Хорошо, я использую необработанный хэш SHA1 для заполнения генератора псевдослучайных чисел Мерсенна Твистера
генератор дает мне возможность посеять либо с беззнаковым длинным, либо с массивом беззнаковых длинных

класс SHA1, который я использую, дает мне хэш в виде 20-байтового массива беззнаковых символов

Я подумал, что мог бы преобразовать этот массив символов в массив длинных, чтобы получить работающее начальное число, но как я могу узнать, как долго получается массив длинных?

пример кода:

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

Я надеюсь, что нет потери данных (так как ни один байт не сбрасывается), так как мне нужно, чтобы криптография оставалась безопасной

0

Решение

Ты можешь сказать

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.
1

Другие решения

Ты можешь использовать len_of_chars * sizeof(char) / sizeof(long), где len_of_chars предположительно 20.

1

Ваша библиотека кажется, предполагает 32-разрядный unsigned longs, так что нет больше вреда, если вы делаете то же самое. На самом деле, я бы пошел так далеко, чтобы предположить, 8-битный unsigned charи, возможно, даже незаполненные представления с прямым порядком байтов для обоих. Таким образом, вы могли бы использовать простое приведение (хотя я бы использовал reinterpret_cast) или, может быть, @ Джина 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), и типы с точной шириной не обязательно будут в нем. Иронический.

0
По вопросам рекламы [email protected]