Подтвердить что ты не робот

Как использовать хэширование SHA1 в программировании на языке C

Я пытаюсь написать программу на C, которая доказывает, что SHA1 почти не содержит конфликтов, но я не могу понять, как на самом деле создать хеш для моих входных значений. Мне просто нужно создать хэш и сохранить шестнадцатеричное значение в массиве. После некоторых поисков Google я нашел документацию OpenSSL, в которой мне было предложено использовать это:

 #include <openssl/sha.h>

 unsigned char *SHA1(const unsigned char *d, unsigned long n,
                  unsigned char *md);

 int SHA1_Init(SHA_CTX *c);
 int SHA1_Update(SHA_CTX *c, const void *data,
                  unsigned long len);
 int SHA1_Final(unsigned char *md, SHA_CTX *c);

Я считаю, что я должен использовать либо unsigned char * SHA1, либо SHA1_Init, но я не уверен, какие аргументы будут, если x - мой вход, который будет хэширован. Кто-нибудь, пожалуйста, очистите это для меня? Спасибо.

4b9b3361

Ответ 1

Если у вас есть все ваши данные одновременно, просто используйте функцию SHA1:

// The data to be hashed
char data[] = "Hello, world!";
size_t length = sizeof(data);

unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
// hash now contains the 20-byte SHA-1 hash

Если, с другой стороны, вы получаете только свои данные за один раз и хотите вычислить хеш при получении этих данных, а затем использовать другие функции:

// Error checking omitted for expository purposes

// Object to hold the current state of the hash
SHA_CTX ctx;
SHA1_Init(&ctx);

// Hash each piece of data as it comes in:
SHA1_Update(&ctx, "Hello, ", 7);
...
SHA1_Update(&ctx, "world!", 6);
// etc.
...
// When you're done with the data, finalize it:
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1_Final(hash, &ctx);

Ответ 2

Это два разных способа достижения одного и того же.

В частности, вы или используете SHA_Init, а затем SHA_Update столько раз, сколько необходимо для передачи ваших данных, а затем SHA_Final, чтобы получить дайджест, или вы SHA1.

Причиной двух режимов является то, что при хэшировании больших файлов обычным является чтение файла в кусках, поскольку альтернатива будет использовать много памяти. Следовательно, отслеживание SHA_CTX - контекста SHA - по мере того, как вы идете, вы можете обойти это. Алгоритм внутри также подходит для этой модели, то есть данные передаются в блоке за раз.

Метод SHA должен быть достаточно простым. Другой работает следующим образом:

unsigned char md[SHA_DIGEST_LENGTH];
SHA_CTX context;
int SHA1_Init(&context);

for ( i = 0; i < numblocks; i++ )
{
    int SHA1_Update(&context, pointer_to_data, data_length);
}
int SHA1_Final(md, &context);

В конечном итоге md будет содержать двоичный дайджест, а не шестнадцатеричное представление - это не строка и не должен использоваться как один.

Ответ 3

Первая функция (SHA1()) - это более высокоуровневая, она, вероятно, та, которую вы хотите. Документ довольно понятен в использовании - d - это вход, n - его размер, а md - это место, где размещен результат (вы его назначаете).

Что касается других 3 функций - это более низкий уровень, и я уверен, что они внутренне используются первым. Они лучше подходят для больших входов, которые необходимо обрабатывать поэтапно.

Ответ 4

Я считаю, что должен использовать либо unsigned char *SHA1, либо SHA1_Init...

Для более поздних версий библиотеки OpenSSL, например 1.0.2 и 1.1.0, проект рекомендует использовать интерфейс EVP. Пример использования EVP Message Digests с SHA256 доступен в вики OpenSSL:

#define handleErrors abort

EVP_MD_CTX *ctx;

if((ctx = EVP_MD_CTX_create()) == NULL)
    handleErrors();

if(1 != EVP_DigestInit_ex(ctx, EVP_sha256(), NULL))
    handleErrors();

unsigned char message[] = "abcd .... wxyz";
unsinged int message_len = sizeof(message);

if(1 != EVP_DigestUpdate(ctx, message, message_len))
    handleErrors();

unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int digest_len = sizeof(digest);

if(1 != EVP_DigestFinal_ex(ctx, digest, &digest_len))
    handleErrors();

EVP_MD_CTX_destroy(ctx);