C: sha256 выводит хеш-функцию в полях массива структуры, вызывая сбой при записи содержимого структуры на диск - PullRequest
0 голосов
/ 17 марта 2019

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

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "openssl/sha.h"
#include <time.h>
#include <math.h>

struct password_struct {
    char password[17];
    char hash[65];
    float entropy;
};

struct password_struct* allocate_heap_memory(int num_passwords);
void orchestrate_value_setting(int num_passwords, struct password_struct* user_password_structs);
void orchestrate_file_output(int num_passwords, struct password_struct* user_password_structs);
void write_results_to_disk(char file_name[], struct password_struct* user_password_structs);
void set_hash_entry(struct password_struct* user_password_structs);

int main(void) {

    int num_passwords = 2;

    struct password_struct* user_password_structs = allocate_heap_memory(num_passwords);

    struct password_struct* allocated_memory_start_ptr = user_password_structs;

    orchestrate_value_setting(num_passwords, user_password_structs);

    user_password_structs = allocated_memory_start_ptr; // Resetting pointer to allow cycling back through all structures for appending data to output file
    orchestrate_file_output(num_passwords, user_password_structs);

    free(allocated_memory_start_ptr);
}


struct password_struct* allocate_heap_memory(int num_passwords) {

    struct password_struct* user_password_structs = malloc(num_passwords * sizeof(struct password_struct));

    if (!user_password_structs) {
        printf("Malloc failed, exiting\n");
        exit(0);
    }

    return user_password_structs;

}

void set_hash_entry(struct password_struct* user_password_structs){

    int pass_entry_length = strlen(user_password_structs->password);
    SHA256_CTX context;
    unsigned char generated_hash[65]; //sha256 standard digest length + 1;    
    SHA256_Init(&context);
    SHA256_Update(&context, (unsigned char *)user_password_structs->password, pass_entry_length);
    SHA256_Final(generated_hash, &context);

    char* hash_ptr = &user_password_structs->hash[0];

    int i;
    for (i=0; i < (64); i++) {
        snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]); // Need to convert from hex to char representation
    }
    user_password_structs->hash[64] = '\0';
    printf("%s\n", user_password_structs->hash);

}

void orchestrate_value_setting(int num_passwords, struct password_struct* user_password_structs) {

        char pw1[10] = "test";
        char pw2[10] = "test2";
        float entropy1 = 5.0;
        float entropy2 = 10.0;
        strcpy(user_password_structs->password, pw1);
        set_hash_entry(user_password_structs);
        user_password_structs->entropy = entropy1;
        user_password_structs++;

        strcpy(user_password_structs->password, pw2);
        set_hash_entry(user_password_structs);
        user_password_structs->entropy = entropy2;
        user_password_structs++;


}

void orchestrate_file_output(int num_passwords, struct password_struct* user_password_structs) {

    printf("Writing data to disk...\n");

    char file_name[20] = "name";
    int i;
    for (i = 0; i < num_passwords; i++) {
        write_results_to_disk(file_name, user_password_structs);
        user_password_structs++;
    }
}

void write_results_to_disk(char file_name[], struct password_struct* user_password_structs) {

    FILE *file_pointer = fopen(file_name, "a");
    if (file_pointer == NULL) {
        printf("Error: Failed to open file\n");
        exit(1);
    }

    fprintf(file_pointer, "%s:%s:%f\n", user_password_structs->password, user_password_structs->hash, user_password_structs->entropy);
    fclose(file_pointer);


}

После запуска этой программы выдается следующий вывод:

9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752
Writing data to disk...
*** Error in `./diagnostic': free(): invalid next size (normal): 0x0804b0c0 ***
Aborted (core dumped)

Я наивно полагал, что это была проблема переполнения, связанная с моей

snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]);

операцией, но увеличение размера хеш-буфера в структуре, похоже, не помогает.Любая помощь будет принята с благодарностью!

Я составил следующее: gcc -o diagnostic -g diagnostic.c -lcrypto -lm

1 Ответ

1 голос
/ 17 марта 2019
char hash[65];

Хорошо, hash имеет место для 65 символов.

char* hash_ptr = &user_password_structs->hash[0];

Итак, hash_ptr указывает на hash, поэтому он указывает на комнату для 65 символов.

for (i=0; i < (64); i++) {
    snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]); // Need to convert from hex to char representation
}

Когда i равно 60, i*2 равно 120. Таким образом, вы пытаетесь записать в 120-ю позицию буфера с местом для 65 символов.

Измените это (64) на32 в цикле или измените hash[65] на больший буфер.

Использование valgrind обнаружило это немедленно.Вы также должны научиться использовать некоторые из них, которые обнаруживают переполнение буфера, использование после освобождения, двойное освобождение и подобные проблемы.

...