C ++: Эффективно ли получить дайджест Sha256 в OpenSSL Bignum? - PullRequest
0 голосов
/ 09 сентября 2018

Задача

Так что я использую C ++ с библиотекой OpenSSL, чтобы попытаться реализовать мой собственный блокчейн с нуля, и все шло очень хорошо, пока я не наткнулся на проблему:

Как я могу хранить свои 256-битные хеш-коды?

Сначала я попытался реализовать свой собственный 256-битный тип из

uint8_t.

но потом я сдался и решил использовать OpenSSL 'bignums.

Но вот, насколько я знаю, бигнумы OpenSSL предназначены для использования в криптографических функциях с открытым ключом, как я могу выполнять хеш-функции, такие как sha256, и сохранять дайджест в BigNum?

Или есть альтернативный вариант, эффективный для хранения 256-битных и более значений?

Вот код, который я использовал перед bignums:

UINT<SHA256_DIGEST_LENGTH> Crypto::Sha256 (const std::string &p_Data)
{
    UINT<SHA256_DIGEST_LENGTH> result;
    SHA256_CTX context;

    SHA256_Init (&context);
    SHA256_Update (&context, p_Data.c_str (), p_Data.length ());
    SHA256_Final (result.m_Bytes, &context);

    return result;
}

Вот моя собственная реализация BigNum: (Не очень эффективно)

template<size_t BLOCK_SIZE>
struct UINT
{
    size_t blockSize = BLOCK_SIZE;
    uint8_t m_Bytes[BLOCK_SIZE];

    static UINT<BLOCK_SIZE> Zero ()
    {
        UINT<BLOCK_SIZE> r;

        for ( uint8_t &byte : r.m_Bytes )
            byte = 0b0000'0000;

        return r;
    }

    static UINT<BLOCK_SIZE> One ()
    {
        UINT<BLOCK_SIZE> r;

        for ( uint8_t &byte : r.m_Bytes )
            byte = 0b1111'1111;

        return r;
    }

    friend std::ostream& operator<<(std::ostream& p_OS, const UINT<BLOCK_SIZE>& p_Value)
    {
        for ( const uint8_t &byte : p_Value.m_Bytes )
            p_OS << (int) byte;

        return p_OS;
    }

    std::string Str ()
    {
        std::stringstream ss;

        for ( const uint8_t &byte : m_Bytes )
            ss << (int) byte;

        return ss.str();
    }

    bool operator==(const UINT<BLOCK_SIZE> &p_Other) const
    {
        bool r = true;

        for ( int i = 0; i < 256; ++i )
        {
            const bool X = (m_Bytes[i / 8] >> (i % 8)) & 1;
            const bool Y = (p_Other.m_Bytes[i / 8] >> (i % 8)) & 1;

            r &= ~(X ^ Y);
        }

        return r;
    }

    bool operator!=(const UINT<BLOCK_SIZE> &p_Other) const
    {
        bool r = true;

        for ( int i = 0; i < 256; ++i )
        {
            const bool X = (m_Bytes[i / 8] >> (i % 8)) & 1;
            const bool Y = (p_Other.m_Bytes[i / 8] >> (i % 8)) & 1;

            r &= X ^ Y;
        }

        return r;
    }

    bool operator>(const UINT<BLOCK_SIZE> &p_Other) const
    {
        bool r = true;

        for ( int i = 0; i < 256; ++i )
        {
            const bool X = (m_Bytes[i / 8] >> (i % 8)) & 1;
            const bool Y = (p_Other.m_Bytes[i / 8] >> (i % 8)) & 1;

            r &= X & ~Y;
        }

        return r;
    }

    bool operator<(const UINT<BLOCK_SIZE> &p_Other) const
    {
        bool r = true;

        for ( int i = 0; i < 256; ++i )
        {
            const bool X = (m_Bytes[i / 8] >> (i % 8)) & 1;
            const bool Y = (p_Other.m_Bytes[i / 8] >> (i % 8)) & 1;

            r &= ~X & Y;
        }

        return r;
    }

    bool operator>=(const UINT<BLOCK_SIZE> &p_Other) const
    {
        bool r = true;

        for ( int i = 0; i < 256; ++i )
        {
            const bool X = (m_Bytes[i / 8] >> (i % 8)) & 1;
            const bool Y = (p_Other.m_Bytes[i / 8] >> (i % 8)) & 1;

            r &= (X & ~Y) | ~(X ^ Y);
        }

        return r;
    }

    bool operator<=(const UINT<BLOCK_SIZE> &p_Other) const
    {
        bool r = true;

        for ( int i = 0; i < 256; ++i )
        {
            const bool X = (m_Bytes[i / 8] >> (i % 8)) & 1;
            const bool Y = (p_Other.m_Bytes[i / 8] >> (i % 8)) & 1;

            r &= (~X & Y) | ~(X ^ Y);
        }

        return r;
    }
};

Также важно отметить: Первоначально я реализовал свою собственную функцию Sha256, но использовать это было бы плохой идеей. Во-первых, я не эксперт в криптографии, во-вторых, с точки зрения масштабируемости это очень плохо, потому что мне пришлось бы также реализовывать все остальные криптографические функции с нуля, поэтому я решил использовать готовые хеш-функции OpenSSL.

Решения, о которых я думал Я думал об установке каждого бита во вновь созданном BigNum, используя BN_set_bit (), однако, это было бы не очень эффективно, поскольку мы уже помещаем дайджест в массив uint8_t. Мы дважды будем копировать результаты, что является глупым решением.

Теперь мне нужна одна из двух вещей:

  • Чтобы сохранить дайджест из Sha256_final или EVP_DigestFinal_ex в bignum
  • Чтобы использовать другую структуру данных для хранения этой информации.

И мне нужно иметь возможность выполнять арифметическое, по крайней мере, 256-битное деление и сравнение с большим равенством.

Пожалуйста, помогите мне !!

1 Ответ

0 голосов
/ 09 сентября 2018

В итоге я использовал BN_bin2bn () для преобразования uint8_t в BigNum.

#include <openssl/bn.h>

void Crypto::Sha256 (const std::string &p_Data, BIGNUM* hash)
{
    uint8_t digestBuffer[256];
    SHA256_CTX context;

    SHA256_Init (&context);
    SHA256_Update (&context, p_Data.c_str (), p_Data.length ());
    SHA256_Final (digestBuffer, &context);

    BN_bin2bn (digestBuffer, 256, hash);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...