Делаем конвертацию похожую на BN_hex2bn + BN_bn2bin без openSSL в C - PullRequest
0 голосов
/ 14 декабря 2018

В настоящее время я использую openSSL для преобразования значений из зашифрованной строки в то, что я считал двоичным массивом.Затем я расшифровываю этот «массив» (переход к EVP_DecryptUpdate).Я делаю преобразование следующим образом:

    BIGNUM *bnEncr = BN_new();
    if (0 == BN_hex2bn(&bnEncr, encrypted)) { // from hex to big number
        printf("ERROR\n");
    }
    unsigned int numOfBytesEncr = BN_num_bytes(bnEncr);
    unsigned char encrBin[numOfBytesEncr];
    if (0 == BN_bn2bin(bnEncr, encrBin)) { // from big number to binary
        printf("ERROR\n");
    }

Затем я передаю encrBin в EVP_DecryptUpdate и расшифровка работает.

Я делаю это во многих местах моего кода и теперь хочу написать свою собственную функцию Cпреобразования шестнадцатеричного в двоичный массив, который я затем могу передать EVP_DecryptUpdate.Я попробовал это и преобразовал свою зашифрованную шестнадцатеричную строку в массив 0 и 1, но оказалось, что EVP_DecryptUpdate не будет работать с этим.Из того, что я мог найти в Интернете, BN_bn2bin «создает действительно двоичное представление (то есть последовательность битов). Более конкретно, оно создает представление числа с прямым порядком байтов».Так что это не просто массив нулей и единиц, верно?

Может кто-нибудь объяснить, как я могу сам выполнить шестнадцатеричное (> истинно) двоичное преобразование в C, чтобы я мог получить формат, который ожидает EVP_DecryptUpdate?Это сложно?

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

BN_bn2bin "создает действительно двоичное представление (то есть последовательность битов). Более конкретно, оно создает представление числа с прямым порядком байтов".Так что это не просто массив из 0 и 1, верно?

Упомянутая здесь последовательность битов представлена ​​в виде массива байтов.С каждым из этих байтов, содержащих 8 битов, это можно интерпретировать как «массив из 0 и 1».Это не «массив целых чисел, который имеет значение 0 или 1», если это то, что вы спрашиваете.

Поскольку вы не знаете, как работает BN_bn2bin(), это помогает просто проанализировать конецрезультат вашего кода.Вы можете сделать это следующим образом (без проверки ошибок):

#include <stdio.h>
#include <openssl/bn.h>

int main(
    int argc,
    char **argv)
{
    const char *hexString = argv[1];

    BIGNUM *bnEncr = BN_new();
    BN_hex2bn(&bnEncr, hexString);
    unsigned int numOfBytesEncr = BN_num_bytes(bnEncr);
    unsigned char encrBin[numOfBytesEncr];
    BN_bn2bin(bnEncr, encrBin);
    fwrite(encrBin, 1, numOfBytesEncr, stdout);
}

Это выводит содержимое encrBin на стандартный вывод, что никогда не бывает приятно, но вы можете затем передать это по конвейеру.с помощью инструмента, подобного hexdump, или перенаправьте его в файл для анализа с помощью шестнадцатеричного редактора.Это выглядит так:

$ ./bntest 74162ac74759e85654e0e7762c2cdd26 | hexdump -C
00000000  74 16 2a c7 47 59 e8 56  54 e0 e7 76 2c 2c dd 26 |t.*.GY.VT..v,,.&|
00000010

Или, если вы хотите увидеть эти 0 и 1:

$ ./bntest  74162ac74759e85654e0e7762c2cdd26 | xxd -b -c 4
00000000: 01110100 00010110 00101010 11000111  t.*.
00000004: 01000111 01011001 11101000 01010110  GY.V
00000008: 01010100 11100000 11100111 01110110  T..v
0000000c: 00101100 00101100 11011101 00100110  ,,.&

Это показывает, что ваш вопрос

Может кто-нибудь объяснить, как я могу сам сделать шестнадцатеричное (> истинно) двоичное преобразование в C, чтобы я получил формат, ожидаемый EVP_DecryptUpdate?Это сложно?

по сути такой же, как и вопрос SO Как превратить шестнадцатеричную строку в массив без знака? , как я прокомментировал .

0 голосов
/ 14 декабря 2018

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

static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
{
    int n;
    size_t i, lasti, j, atop, mask;
    BN_ULONG l;

    /*
     * In case |a| is fixed-top, BN_num_bytes can return bogus length,
     * but it's assumed that fixed-top inputs ought to be "nominated"
     * even for padded output, so it works out...
     */
    n = BN_num_bytes(a);
    if (tolen == -1) {
        tolen = n;
    } else if (tolen < n) {     /* uncommon/unlike case */
        BIGNUM temp = *a;

        bn_correct_top(&temp);
        n = BN_num_bytes(&temp);
        if (tolen < n)
            return -1;
    }

    /* Swipe through whole available data and don't give away padded zero. */
    atop = a->dmax * BN_BYTES;
    if (atop == 0) {
        OPENSSL_cleanse(to, tolen);
        return tolen;
    }

    lasti = atop - 1;
    atop = a->top * BN_BYTES;
    for (i = 0, j = 0, to += tolen; j < (size_t)tolen; j++) {
        l = a->d[i / BN_BYTES];
        mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1));
        *--to = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
        i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */
    }

    return tolen;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...