Как вычислить га sh для структуры - PullRequest
2 голосов
/ 10 января 2020

Я ищу решение, как вычислить га sh для структуры данных. Давайте предположим, что у нас есть такая структура:

struct A
{
    float64_t array[4][4];
    float64_t x;
    float64_t y;
    uint8_t validationHash[32]; // here computed hash need to be stored
}

У меня также есть функция Sha256(cont char * input, uint8_t (&output)[32]), которая в качестве аргумента принимает ввод и вывод - вычисляется ha sh. Я знаю, что мне нужно преобразовать каждое значение из структуры в const char *. Но мой вопрос в том, что делать дальше, я должен вычислить отдельное значение ha sh для каждого значения из массива, x и y и сложить их вместе или как?

Реализация Sha256 такая же, как здесь http://www.zedwood.com/article/cpp-sha256-function

1 Ответ

2 голосов
/ 10 января 2020

Функция 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.

...