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

Void bf_set_key(bf_key *key, int len, const unsigned char *data);

Задача этой функции - поместить ключ длиной len из буфера data в структуру key.

Криптопреобразование данных в режиме CFB c 64битной обратной связью выполняет функция BF_cfb64_encrypt:

Void bf_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length, const bf_key *schedule, unsigned char *ivec, int *num, int enc);

Думаю, что после того как мы рассмотрели DES, никому не составит труда разобраться в назначении параметров этой функции. Остановимся только на последнем параметре - int enc. Он задает режим работы алгоритма и может принимать два значения: BF_ENCRYPT для режима шифрования и BF_DECRYPT для режима дешифрования. Оба эти значение определены в файле openssl/blowfish.h:

#define BF_ENCRYPT 1

#define BF_DECRYPT 0

А теперь оформим все теоретические выкладки в виде функции криптографического преобразования информации по алгоритму Blowfish, работающему в режиме 64битной обратной связи (CFB-64).

Листинг 6. Функция криптографического преобразования информации по алгоритму Blowfish, режим 64-битной обратной связи (CFB-64)

#include <openssl/blowfish.h>

#define BUFSIZE 1024

/* Функция криптопреобразования информации. Параметры функции: дескрипторы входного и выходного

файлов и режим работы - BF_ENCRYPT для шифрования и BF_DECRYPT для дешифрования */

Int do_crypt(file *in, file *out, int mode)

{

int num = 0;

unsigned char inbuf[BUFSIZE], outbuf[BUFSIZE];

/* Ключ шифрования длиной 128 бит и вектор инициализации */

const unsigned char key[16];

unsigned char iv[8];

BF_KEY bfkey;

/* Помещаем ключ в структуру bfkey */

BF_set_key(&bfkey, sizeof(key), key);

/* Шифруем блоки входного файла */

for(;;) {

int inlen = fread(inbuf, 1, BUFSIZE, in);

if(inlen <= 0) break;

BF_cfb64_encrypt(inbuf, outbuf, (long)inlen, &bfkey, iv, &num, mode);

fwrite(outbuf, 1, inlen, out);

}

return 1;

}

Следующий фрагмент функции иллюстрирует порядок криптопреобразования по алгоритму Blowfish, режим 64битной обратной связи по выходу (OFB-64).

Листинг 7. фрагмент функции криптографического преобразования информации по алгоритму Blowfish, режим 64-битной обратной связи по выходу (OFB-64)

Void do_crypt(file *in, file *out)

{

unsigned char inbuf[BUFSIZE];

unsigned char outbuf[BUFSIZE];

/* Ключ и вектор инициализации */

. . .

BF_set_key(&bfkey, KEY_SIZE, key);

for(;;) {

int inlen = fread(inbuf, 1, BUFSIZE, in);

if(inlen <= 0) break;

BF_ofb64_encrypt(inbuf, outbuf, (long)inlen, &bfkey, iv, &num);

fwrite(outbuf, 1, inlen, out);

}

}

Использование высокоуровневых функций библиотеки для шифрования

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

Контекст алгоритма шифрования представляет собой структуру типа EVP_CIPHER_CTX, определенную в файле openssl/evp.h. Первым элементом этой структуры является указатель на структурный тип EVP_CIPHER следующего вида:

struct evp_cipher_st {

int nid;

int block_size;

int key_len; /* Default value for variable length ciphers */

int iv_len;

unsigned long flags; /* Various flags */

int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc); /* init key */

int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl);/* encrypt/decrypt data */

int (*cleanup)(EVP_CIPHER_CTX *); /* cleanup ctx */

int ctx_size; /* how big ctx->cipher_data needs to be */

int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *);

int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *);

int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr);

void *app_data; /* Application data */

} /* EVP_CIPHER */;

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

Первый способ подразумевает поиск по символьному имени алгоритма:

OpenSSL_add_all_ciphers();

const EVP_CIPHER * cipher = EVP_get_cipherbyname("des_cbc");

Функция EVP_get_cipherbyname(const char * name) извлекает адреса функций алгоритма шифрования из внутренней таблицы библиотеки и заполняет структуру cipher. Входные параметры функции - символьное имя алгоритма, в данном случае это DES, режим CBC. Перечень всех имен содержится в файле openssl/object.h.

Второй способ - прямое обращение к нужной EVP-функции:

const EVP_CIPHER *cipher = EVP_des_cbc();

Получив адреса функций, инициализируем контекст алгоритма:

EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx);

EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, const unsigned char *key, const unsigned char *iv);

Функция EVP_CIPHER_CTX_init обнуляет структуру, выделенную под контекст. Инициализацию контекста выполняет функция EVP_EncryptInit(). Параметры функции - указатель на контекст алгоритма ctx, структура с адресами библиотечных функций алгоритма cipher, блок с ключевыми данными key и вектор инициализации iv.

После инициализации контекста можно приступать к операции шифрования. Делает это функция EVP_EncryptUpdate():

int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);

Функция шифрует inl байтов из буфера in и записывает зашифрованные данные в буфер out. В переменной outl сохраняется количество зашифрованных байтов.

Если размер сообщения не кратен размеру блока шифрования, то выполняется вызов функции EVP_EncryptFinal, которая "дошифровывает" оставшиеся данные:

int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);

Следующий код демонстрирует использование функций высокого уровня для шифрования файла по алгоритму AES с ключом длиной 256 бит, режим 64-битовой шифрованной обратной связи CFB.

Листинг 8. Шифрование файла по алгоритму AES, длина ключа 256 бит, режим 64-битовой шифрованной обратной связи

#include <openssl/evp.h>

#define BUFSIZE 1024

int do_crypt(char *infile)

{

int outlen, inlen;

FILE *in, *out;

unsigned char key[32]; /* 256- битный ключ */

unsigned char iv[8]; /* вектор инициализации */

unsigned char inbuf[BUFSIZE], outbuf[BUFSIZE];

EVP_CIPHER_CTX ctx;

const EVP_CIPHER * cipher;

/* Обнуляем структуру контекста */

EVP_CIPHER_CTX_init(&ctx);

/* Выбираем алгоритм шифрования */

cipher = EVP_aes_256_cfb();

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

EVP_EncryptInit(&ctx, cipher, key, iv);

/* Шифруем данные */

for(;;) {

inlen = fread(inbuf, 1, BUFSIZE, in);

if(inlen <= 0) break;