Если у вас возникли проблемы с чтением содержимого файла, до до вызова кода хеш-функции, тогда ваша проблема не связана с хешированием.
Вы должны использовать стандартную функцию fopen()
вместо _tfopen()
. В C вещей, которые начинаются с символа подчеркивания, часто лучше избегать. Тем более, что _tfopen()
, по-видимому, соответствует либо fopen()
, либо специфичному для Windows _wfopen()
в зависимости от того, активирована ли так называемая "поддержка юникода". Кроме того, в чисто Windows-приложении вы можете использовать такие функции Win32, как CreateFile()
.
Чтение всего файла в памяти и последующее хеширование - это сырая. Например, он не сможет обрабатывать файлы, размер которых превышает объем доступной оперативной памяти. Кроме того, чтобы узнать размер файла, вы должны искать в нем, что ненадежно (могут быть псевдофайлы, которые на самом деле являются каналами в некоторый процесс генерации данных, поиск которого невозможен). Хеш-функции могут обрабатывать данные кусками; Вы должны использовать небольшой буфер (8 кБ это традиционный размер) и использовать функции SHA1_Init()
, SHA1_Update()
и SHA1_Final()
.
fread()
не обязательно считывает столько данных, сколько вы запрашивали. И это не ошибка.
Когда вы звоните SHA1()
, вы используете strlen()
в своем буфере, который является поддельным. strlen()
возвращает длину строки символов ; Проще говоря, число байтов до следующего байта значения ноль. Многие файлы содержат байты со значением 0. А если этого файла нет, то нет никакой гарантии, что в вашем буфере есть какой-либо байт со значением 0, так что вызов strlen()
может закончить чтение памяти вне выделенного буфера (это плохо ). Поскольку вы столкнулись с проблемой получения длины файла и выделения такого большого буфера, вы должны по крайней мере использовать эту длину вместо попытки пересчитать ее с помощью функции, которая этого не делает.
Подводя итог: ваш код должен выглядеть так (не проверено):
/*
* Hash a file, which name is given. Hash output is written out in
* buffer "out[]". The hash output consists in exactly 20 bytes.
* On success, 0 is returned; on error, returned value is -1 and
* out[] is unaltered.
*/
int
do_sha1_file(char *name, unsigned char *out)
{
FILE *f;
unsigned char buf[8192];
SHA_CTX sc;
int err;
f = fopen(name, "rb");
if (f == NULL) {
/* do something smart here: the file could not be opened */
return -1;
}
SHA1_Init(&sc);
for (;;) {
size_t len;
len = fread(buf, 1, sizeof buf, f);
if (len == 0)
break;
SHA1_Update(&sc, buf, len);
}
err = ferror(f);
fclose(f);
if (err) {
/* some I/O error was encountered; report the error */
return -1;
}
SHA1_Final(out, &sc);
return 0;
}
И не забудьте включить соответствующие заголовки файлов! (<stdio.h>
и sha.h
от OpenSSL)