Mam problemy z próby generowania losowych tablic z funkcją RAND_bytes() z OpenSSL.

Wersja OpenSSL:

OpenSSL 1.1.0g  2 Nov 2017 (Library: OpenSSL 1.1.1  11 Sep 2018)
built on: Tue Nov 12 16:58:35 2019 UTC
platform: debian-amd64
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -fdebug-prefix-map=/build/openssl-kxN_24/openssl-1.1.1=. -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPADLOCK_ASM -DPOLY1305_ASM -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
OPENSSLDIR: "/usr/lib/ssl"
ENGINESDIR: "/usr/lib/x86_64-linux-gnu/engines-1.1"

Generuj_salt.c.

#include <openssl/rand.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

uint8_t *generate_salt()
{
    uint8_t *res = malloc(16 * sizeof(uint8_t));
    RAND_bytes(res, 16);
    return res;
}

void print_hexa(uint8_t *message)
{
    int message_length = 0;
    while (message[message_length] != '\0')
    {
        message_length += 1;
    }
    for (int i = 0; i < message_length; i++)
    {
        printf("%02x", message[i]);
    }
    printf(";\n");
}
int main()
{
    for (int i = 0; i < 20; i++)
    {
        print_hexa(generate_salt());
    }
}

Wynik:

05b3c470b709ef345b;
862c53a9;
1aa1665fe26aa04a7cdc9e63a14b8859;
e093b250e55172c6a12eb21a14146b52;
7de470cf708249bd81571a9fe1362618;
7fccff3509fb0189a954784ce198e3cd;
ba98881d1023a5f4d4c5a2c829ce26c3;
63e0f027a057de8f0e32e595f7cd4df2;
6faa5ab05413c5566a3b05783dfaa086;
ae2e91741d0dabd6ba7d0ae55885540f;
cd49f8c218cfdaf02dfd6fa53e523e51;
2fd24cb9e2d6e7b992eb28a2ffa5af44;
5c6f6ffb62784c87cc25ba25c6ba;
56a0cc97d008ee65b0b6f78eb094fcee;
9d1ef2ef40966dca1991364fa83d134d;
2ab61566cdd9a0d2bf09b2634b112cd2;
7064ffe72ccb9f9eb2954c0c59477fd8;
100e0c34e64d2f6f788c6fe7b908b181;
67bb8b232d1ab2ada5632c0e5fbb0f4f;
f55df4049bf0c477fdf6121399e5c116;

Moim problemem jest to, że niektóre z wyników nie są danej długości (16 bajtów). Mam podobne problemy z funkcjami, których używam z modułu openssl/evp.h. Po raz pierwszy pomyślałem, że miałem pewne problemy związane z pamięcią, dlatego dokonałem oddzielnego pliku generate_salt.c, który wydaje mi się udowodnić.

Czy ktoś kiedykolwiek spotkał się z tym i wie, jak go rozwiązać?

Używam WSL (Linux Bash na Windows), co może być kolejnym powodem, dla którego nie działa prawidłowo. Być może OpenSSL wymaga rzeczywistego jądra Linuksa.

Edytuj: Jak sugerował w akceptowanej odpowiedzi, implementacja print_hexa jest błędna. Podczas gdy stan prowadzi do wyświetlania błędów, gdy bajt 0x00 pojawi się w tablicy bajtowej (i może również spowodować, że Segfault). Długość powinna być podana jako argument lub kodowany w funkcji. Nie ma sposobu na uzyskanie długości wskaźnika w C.

1
Quentin Biharé 26 październik 2020, 22:08

1 odpowiedź

Najlepsza odpowiedź

Twoja implementacja print_hexa jest błędna. Losowe bajty mogą zawierać 0x00, a funkcja może się tam zatrzymać. Jeszcze gorsze jest to, że jeśli losowe bajty nie zawierają 0x00, zrobi dostęp do dostępu do znalezienia 0x00.

Aby uniknąć tego problemu, długość do drukowania należy podać oddzielnie print_hexa.

#include <openssl/rand.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

uint8_t *generate_salt()
{
    uint8_t *res = malloc(16 * sizeof(uint8_t));
    RAND_bytes(res, 16);
    return res;
}

void print_hexa(uint8_t *message, int message_length)
{
    for (int i = 0; i < message_length; i++)
    {
        printf("%02x", message[i]);
    }
    printf(";\n");
}
int main()
{
    for (int i = 0; i < 20; i++)
    {
        print_hexa(generate_salt(), 16);
    }
}

Inny wybór jest trudny do kodowania długości, ponieważ w funkcji generate_salt.

#include <openssl/rand.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

uint8_t *generate_salt()
{
    uint8_t *res = malloc(16 * sizeof(uint8_t));
    RAND_bytes(res, 16);
    return res;
}

void print_hexa(uint8_t *message)
{
    for (int i = 0; i < 16; i++)
    {
        printf("%02x", message[i]);
    }
    printf(";\n");
}
int main()
{
    for (int i = 0; i < 20; i++)
    {
        print_hexa(generate_salt());
    }
}

Definiowanie długości, ponieważ makro jest lepsze niż pisanie Magic Number 16 bezpośrednio.

#include <openssl/rand.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

#define LENGTH 16

uint8_t *generate_salt()
{
    uint8_t *res = malloc(LENGTH * sizeof(uint8_t));
    RAND_bytes(res, LENGTH);
    return res;
}

void print_hexa(uint8_t *message)
{
    for (int i = 0; i < LENGTH; i++)
    {
        printf("%02x", message[i]);
    }
    printf(";\n");
}
int main()
{
    for (int i = 0; i < 20; i++)
    {
        print_hexa(generate_salt());
    }
}
3
MikeCAT 26 październik 2020, 19:14