Mpz_init_set_str GMP вызывает ошибку realloc - PullRequest
0 голосов
/ 17 июня 2019

Я работаю над проектом, использующим gmp для реализации базового обмена DH. В этом обмене есть две основные функции: одна для создания открытого ключа из закрытого ключа, а другая для генерации общего секрета с помощью закрытого ключа и открытого ключа.

Во время первой функции мои вызовы в gmp lib работают как положено. Во время второй функции мой вызов mpz_init_set_str либо вызывает ошибку сегмента, либо прерывает работу с сообщением

realloc (): неверный старый размер Прервано (ядро сброшено)

или

malloc.c: 2868: mremap_chunk: Ошибка утверждения `((размер + смещение) & (GLRO (dl_pagesize) - 1)) == 0 '.

Строка, вызывающая это, дословно используется в первой функции, и я не могу понять, что вызывает это.

Ниже приведен пример программы, которая демонстрирует проблему при запуске на моем компьютере. Я использую gcc (Ubuntu 7.4.0-1ubuntu1 ~ 18.04.1) 7.4.0. и libgmp10 версия 2: 6.1.2 + dfsg-2

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "gmp.h"
#include "time.h"

#define SECRET_KEY_SIZE             64
#define PRIVATE_KEY_SIZE            512

#define DH_KEY_EXCHANGE_P "96C99B60C4F823707B47A848472345230C5B25103DC37412A701833E8FF5C567A53A41D0B37B10F0060D50F4131C57CF1FD11B6A6CB958F36B1E7D878A4C4BC7"
#define DH_KEY_EXCHANGE_G "2C900DF142E2B839E521725585A92DC0C45D6702A48004A917F74B73DB26391F20AEAE4C6797DD5ABFF0BFCAECB29554248233B5E6682CE1C73DD2148DED76C3"

#define BASE_HEX            16
#define BASE_RADIX          32

char intToCharBase32(int input)
{
    char ret = 0;
    if(input <= 9)
    {
        ret = '0' + input;
    }
    else if(input < 32)
    {
        ret = (input - 10) + 'A';
    }
    return ret;
}

void generateRandomKey(char *random_number_buffer, int len)
{
    short int n;
    srand(time(0));
    for(int i=0; i<len; i++)
    {
        n = rand() % BASE_RADIX;
        random_number_buffer[i] = intToCharBase32(n);
    }
    random_number_buffer[len] = '\0';
}

void calculateDHPublicKey(char *public_key, char *private_key)
{
    mpz_t p;
    mpz_t g;
    mpz_t b;
    mpz_t B;

    mpz_init (B);
    mpz_init_set_str (p, DH_KEY_EXCHANGE_P, BASE_HEX);
    mpz_init_set_str (g, DH_KEY_EXCHANGE_G, BASE_HEX);
    mpz_init_set_str (b, private_key, BASE_RADIX);

    mpz_powm (B, g, b, p);

    mpz_get_str(public_key, BASE_RADIX, B);

    mpz_clear (p);
    mpz_clear (g);
    mpz_clear (b);
    mpz_clear (B);
}

void calculateDHSharedSecret(unsigned char *dh_key_buffer, char *own_private_key, char *other_public_key)
{
    mpz_t p;
    mpz_t b;
    mpz_t A;
    mpz_t SS;

    mpz_init (SS);
    mpz_init_set_str (p, DH_KEY_EXCHANGE_P, BASE_HEX); // <--This line crashes
    mpz_init_set_str (b, own_private_key, BASE_RADIX);
    mpz_init_set_str (A, other_public_key, BASE_RADIX);

    mpz_powm (SS, A, b, p);

    size_t size = 0;

    //todo: move this to the right place (add leading zeros as needed);
    mpz_export(dh_key_buffer, &size, 1, -1, 0, 0, SS);

    mpz_clear (p);
    mpz_clear (b);
    mpz_clear (A);
    mpz_clear (SS);
}

int main (){

    char* private_key = malloc(sizeof(char) * (PRIVATE_KEY_SIZE / BASE_RADIX + 2));
    generateRandomKey(private_key, PRIVATE_KEY_SIZE / BASE_RADIX);
    fprintf(stderr, "Private Key: %s\n", private_key);

    //step 2: generate public key
    char* public_key = malloc(sizeof(char) * (2048 / BASE_RADIX + 1));
    calculateDHPublicKey(public_key, private_key);

    //step 3: share the public key
    fprintf(stderr, "Public Key: %s\n", public_key);

    //step 4: Calculate shared secret
    unsigned char* sharedSecret = malloc(sizeof(unsigned char) * SECRET_KEY_SIZE);
    memset(sharedSecret, 0, SECRET_KEY_SIZE);

    char* other_pk = "1";
    //for debugging just use 1 as the other side of dh handshake
    calculateDHSharedSecret(sharedSecret, private_key, other_pk);

    //step 5: release resources
    free(private_key);
    free(public_key);
    return 0;
}

Я попытался использовать mpz_init, а затем mpz_set_str вместо mpz_init_set_str, и функция все еще прерывается.

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

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

...