Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
PoIRoCSaN_Lab_1.1(openssl).doc
Скачиваний:
9
Добавлен:
18.02.2023
Размер:
270.34 Кб
Скачать

Void md5_Init(md5_ctx * ctx);

Void md5_Update(md5_ctx * ctx, const void * data, unsigned long len);

Void md5_Final(unsigned char * md, md5_ctx * ctx);

Функция MD5_Init() инициализирует контекст дайджеста - структуру, определенную в файле openssl/md5.h:

typedef struct MD5state_st {

MD5_LONG A,B,C,D;

MD5_LONG Nl,Nh;

MD5_LONG data[MD5_LBLOCK]; /* MD5_LBLOCK = 16 */

int num;

} MD5_CTX;

Инициализация контекста подразумевает его заполнение определенными значениями (см. файл md5_dgst.c исходных текстов библиотеки):

#define INIT_DATA_A (unsigned long)0x67452301L

#define INIT_DATA_B (unsigned long)0xefcdab89L

#define INIT_DATA_C (unsigned long)0x98badcfeL

#define INIT_DATA_D (unsigned long)0x10325476L

Int md5_Init(md5_ctx *c)

{

c->A=INIT_DATA_A;

c->B=INIT_DATA_B;

c->C=INIT_DATA_C;

c->D=INIT_DATA_D;

c->Nl=0;

c->Nh=0;

c->num=0;

return 1;

}

Функция MD5_Update() вычисляет хэш. Входными параметрами этой функции являются указатель на контекст хэша ctx, указатель на блок входных данных data и размер этого блока len. Функция MD5_Final() помещает вычисленный хэш из контекста ctx в выходной буфер md, размер которого должен быть равен 16 байт.

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

Листинг 2. Вычисление MD5-хэша для файла большого размера

#include <openssl/md5.h>

#define BUFSIZE (1025*16)

Void main(int argc, char **argv)

{

MD5_CTX c; /* контекст хэша */

unsigned char buf[BUFSIZE];

unsigned char md_buf[MD5_DIGEST_LENGTH];

/* В командной строке передается имя файла, для которого вычисляется хэш */

int inf = open(argv[1], O_RDWR);

/* Инициализируем контекст */

MD5_Init(&c);

/* Вычисляем хэш */

for(;;) {

int i = read(inf, buf, BUFSIZE);

if(i <= 0) break;

MD5_Update(&c, buf, (unsigned long)i);

}

/* Помещаем вычисленный хэш в буфер md_buf */

MD5_Final(md_buf, &c);

/* Отображаем результат */

for(i = 0; i < MD5_DIGEST_LENGTH; i++) printf("%02x", md_buf[i]);

}

Проверить правильность вычисления хэша можно при помощи утилиты md5sum.

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

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

Извлечь структуру требуемого алгоритма хэширования из таблицы можно при помощи функции EVP_get_digestbyname(const char * name), где name является символьным обозначением алгоритма. Для алгоритма MD5 это будет "md5". Список всех имен приведен в файле openssl/object.h. Результат работы функции EVP_get_digestbyname() сохраняется в структуре типа EVP_MD:

struct env_md_st

{

int type;

int pkey_type;

int md_size;

unsigned long flags;

int (*init)(EVP_MD_CTX *ctx);

int (*update)(EVP_MD_CTX *ctx,const void *data,unsigned long count);

int (*final)(EVP_MD_CTX *ctx,unsigned char *md);

int (*copy)(EVP_MD_CTX *to,const EVP_MD_CTX *from);

int (*cleanup)(EVP_MD_CTX *ctx);

/* FIXME: prototype these some day */

int (*sign)();

int (*verify)();

int required_pkey_type[5]; /*EVP_PKEY_xxx */

int block_size;

int ctx_size; /* how big does the ctx->md_data need to be */

} /* EVP_MD */;

Эта структура определена в файле openssl/evp.h. В ее состав входят указатели на функции алгоритма хэширования. При вызове функции EVP_get_digestbyname() в эти указатели будут записаны реальные адреса функций библиотеки для работы с выбранным типом алгоритма хэширования, и в дальнейшем все вызовы функций будут выполняться косвенно через эти указатели. Получив адреса библиотечных функций, необходимо заполнить контекст для вычисления хэша - структуру типа EVP_MD_CTX (см. openssl/evp.h):

struct env_md_ctx_st

{

const EVP_MD *digest;

ENGINE *engine;

unsigned long flags;