Использование SHA1 OpenSSL с Apple Silicon в C

Я создаю клон git и работаю над командой hash-file. В настоящее время я пытаюсь вычислить хеш SHA1 известной строки и имею этот код и следующую проблему:

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

int hashFile(char *file_name, int ww) {
    int i, ret;
    size_t size_len;
    unsigned long file_size;
    char path[56];
    unsigned char hash[SHA_DIGEST_LENGTH];
    char *token, *type, *blob_content, *content;

    FILE *src = fopen(file_name, "r");
    if (ferror(src)) {
        perror("Unable to read file");
        return 1;
    }
    fseek(src, 0L, SEEK_END);
    file_size = ftell(src);
    rewind(src);
    size_len = snprintf(NULL, 0, "%lu", file_size);

    char *buffer = (char *)malloc((size_t)file_size + 1);
    fread(buffer, sizeof(char), file_size, src);
    buffer[file_size] = '\0';

    blob_content = (char *)malloc((7 + sizeof(unsigned long) + file_size + 1) *
                                  sizeof(char));
    snprintf(blob_content, 7 + size_len + 1, "blob %lu\\0", file_size);
    strcat(blob_content, buffer);

    SHA1((unsigned char *)blob_content, strlen(blob_content), hash);
    printf("%s\n", hash);

    free(blob_content);
    free(buffer);

    return 0;
}

void printHashHelp() {
    printf("usage: twat hash-file [options] <file_name>\n");
    printf("\n");
    printf("options:\n");
    printf("\t-w: write contents to objects store\n");
}
$ clang --std=c17 -fmodules -fprebuilt-module-path=. -I/opt/homebrew/opt/openssl/include cmd.c comp.c init.c cat.c hash.c -o twat -v
...
Undefined symbols for architecture arm64:
  "_SHA1", referenced from:
      _hashFile in hash-fc3ff3.o
ld: symbol(s) not found for architecture arm64

Как мне связать и включить SHA1 для работы на M2 Max? Какую команду clang мне следует использовать, если это неверно?

Я пробовал разные методы связывания openssl/sha.h и полагал, что у меня это получилось, но в настоящее время эта функция не работает.

Далее: Как использовать хеширование SHA1 в программировании на C Я попытался использовать связанную библиотеку, но компилятор не смог связать ее.

Во-первых, FILE *src = fopen(file_name, "r"); if (ferror(src))?? Почему вы используете ferror(), чтобы проверить, удалось ли fopen()? fopen() возвращает NULL в случае неудачи, а ferror(NULL) вызывает неопределенное поведение. Во-вторых, вы открываете файл в текстовом режиме, а это значит, что ftell() не дает вам подсчета байтов. На самом деле, использование fseek()/ftell() для получения размера файла в корне неверно. См. stackoverflow.com/questions/8236/…. Вам необходимо хешировать содержимое файла, каким бы оно ни было. А как ты собираешься хешировать файл размером 382 ГБ?

Andrew Henle 29.05.2024 00:21

Примечание. Если в вашем файле есть какие-либо двоичные данные, ваша уверенность в том, что strcat и snprintf сделают правильные действия, приведет к непредсказуемым результатам.

selbie 29.05.2024 00:27

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

h5law 29.05.2024 00:33

@selbie Я думаю, это будет использоваться только для текстовых данных - что бы вы порекомендовали для их обобщения?

h5law 29.05.2024 00:35

@ h5law - Я обновил свой ответ, добавив еще несколько советов по улучшению после того, как вы приняли его. Надеюсь это поможет.

selbie 29.05.2024 00:35

@ h5law - если вы используете «rb» в Windows с fopen, это поможет обеспечить совместимость, поскольку \r\n не будет переводиться по-другому. Смотрите мой обновленный ответ ниже.

selbie 29.05.2024 00:36
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Добавить

-L/opt/homebrew/lib -lcrypto

в вашу командную строку.

Кроме того, ваши malloc и snprintf выглядят странно. Все +1 и +7 выглядят подверженными ошибкам.

Это было бы лучше:

char header[100] = {0};  // 100 is big enough for the entire "blob 12345" thing regardless of how big the file is

SHA1_CTX ctx = {0};
SHA1_Init(&ctx);
sprintf(header, "blob %lu", file_size);
SHA1_Update(&ctx, header, strlen(header));
SHA1_Update(&ctx, buffer, file_size);
SHA1_Final(hash, &ctx);

И затем, если вы действительно хотите быть педантическим, убедитесь, что вы открываете файл как двоичный в не-Unix:

#ifdef _WIN32
    char* flags = "rb";
#else
    char* flags = "r";
#endif

FILE *src = fopen(file_name, flags);

убедитесь, что вы открываете файл как двоичный файл на платформах, отличных от Unix. Думаю, было бы проще просто открыть его в двоичном виде с помощью "rb" на всех платформах.

Andrew Henle 29.05.2024 00:44

Начиная с [email protected], команды Init Update и Final устарели в соответствии с их документацией в пользу команды SHA1. Странный malloc заключается в том, что blob_content должен хранить весь файл. Я думаю, что запись на диск может быть лучшим вариантом по сравнению с сохранением строки в памяти, а не во временном файле.

h5law 29.05.2024 00:59

@AndrewHenle - у меня не было возможности посмотреть это, но я думал, что некоторые платформы не распознают «b» как флаг для fopen, даже если это было неактивно. Возможно, это уже не так.

selbie 29.05.2024 03:31

@selbie Возможно, хотя это, вероятно, уже устарело. C99, похоже, требует поддержки флага b . И неизвестно, как это вообще будет работать на z/OS...

Andrew Henle 29.05.2024 17:53

Другие вопросы по теме