Функция SHA-256 ha sh, с которой вы связаны, как и большинство реализаций cryptographi c ha sh, принимает байтовый массив в качестве входных данных. Итак, самый первый шаг - сериализация данных, которые вы хотите получить sh.
Это не так тривиально, как приведение вашей структуры к байтовому массиву. Сериализация должна быть переносимой между операционными системами и оборудованием. Выравнивание структур, порядковый номер и т. Д. c могут различаться в зависимости от системы, поэтому лучше использовать библиотеку сериализации и оставить все эти хитрые строгие вопросы с псевдонимами авторам библиотеки.
Лучший вариант : Библиотека сериализации
Поскольку вы уже используете Boost (тип float64_t
), вы можете использовать библиотеку сериализации Boost. Сначала создайте функцию сериализации, чтобы инструктировать Boost, как сериализовать A
:
namespace boost {
namespace serialization {
template<class Archive>
void serialize(Archive & ar, A & a, const unsigned int version)
{
ar & a.array;
ar & a.x;
ar & a.y;
}
} // namespace serialization
} // namespace boost
Затем сериализовать ее в поток в памяти:
std::ostringstream plaintext_buffer {};
{
boost::archive::binary_oarchive oa(plaintext_buffer);
oa << a;
}
std::string plaintext = plaintext_buffer.str();
Теперь вы можете использовать SHA-256 га sh функция. Я оставлю эту часть в качестве упражнения для вас.
- Ввод:
plaintext.data()
для данных и plaintext.size()
для размера - Выход:
a.validationHash
Хороший вариант: пользовательский сериализатор с плавающей запятой
Согласно комментариям, вы ограничены C ++ 03 (я возьму это как C ++ 98) и не можете использовать никакие библиотеки. Итак, во-первых, давайте переопределим вашу функцию с использованием ближайших эквивалентных стандартных типов:
struct A
{
double array[4][4];
double x;
double y;
uint8_t validationHash[32]; // here computed hash need to be stored
}
Я слегка адаптировал этот ответ: Сериализируем double и передаем с помощью C, который претендует на переносимость IEEE 754 сериализатор. Круто! Я изменил вывод в буфер памяти, заменил goto
и преобразовал C приведение к static_cast
.
void serializeIeee754(double x, uint8_t* destination)
{
int shift;
unsigned long sign, exp, hibits, hilong, lowlong;
double fnorm, significand;
int expbits = 11;
int significandbits = 52;
if(x == 0) {
/* zero (can't handle signed zero) */
hilong = 0;
lowlong = 0;
} else if(x > DBL_MAX) {
/* infinity */
hilong = 1024 + ((1 << (expbits - 1)) - 1);
hilong <<= (31 - expbits);
lowlong = 0;
} else if(x < -DBL_MAX) {
/* -infinity */
hilong = 1024 + ((1 << (expbits - 1)) - 1);
hilong <<= (31 - expbits);
hilong |= (1 << 31);
lowlong = 0;
} else if(x != x) {
/* NaN - dodgy because many compilers optimise out this test
* isnan() is C99, POSIX.1 only, use it if you will.
*/
hilong = 1024 + ((1 << (expbits - 1)) - 1);
hilong <<= (31 - expbits);
lowlong = 1234;
} else {
/* get the sign */
if(x < 0) {
sign = 1;
fnorm = -x;
} else {
sign = 0;
fnorm = x;
}
/* get the normalized form of f and track the exponent */
shift = 0;
while(fnorm >= 2.0) {
fnorm /= 2.0;
shift++;
}
while(fnorm < 1.0) {
fnorm *= 2.0;
shift--;
}
/* check for denormalized numbers */
if(shift < -1022) {
while(shift < -1022) {
fnorm /= 2.0;
shift++;
}
shift = -1023;
} else {
/* take the significant bit off mantissa */
fnorm = fnorm - 1.0;
}
/* calculate the integer form of the significand */
/* hold it in a double for now */
significand = fnorm * ((1LL << significandbits) + 0.5f);
/* get the biased exponent */
exp = shift + ((1 << (expbits - 1)) - 1); /* shift + bias */
/* put the data into two longs */
hibits = static_cast<long>(significand / 4294967296); /* 0x100000000 */
hilong = (sign << 31) | (exp << (31 - expbits)) | hibits;
lowlong = static_cast<unsigned long>(significand - hibits * 4294967296);
}
destination[0] = lowlong & 0xFF;
destination[1] = (lowlong >> 8) & 0xFF;
destination[2] = (lowlong >> 16) & 0xFF;
destination[3] = (lowlong >> 24) & 0xFF;
destination[4] = hilong & 0xFF;
destination[5] = (hilong >> 8) & 0xFF;
destination[6] = (hilong >> 16) & 0xFF;
destination[7] = (hilong >> 24) & 0xFF;
}
Теперь вы можете написать свой собственный сериализатор для A
, который записывает в 144-байтовый буфер:
void serializeA(A& a, uint8_t destination[144]) {
uint8_t* out = destination;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
serializeIeee754(a.array[i][j], out);
out += 8;
}
}
serializeIeee754(a.x, out);
out += 8;
serializeIeee754(a.y, out);
}
Затем укажите этот буфер для функции ha sh.