Цифровая подпись

ROTATE_LEFT

Данный макрос сдвигает x влево на n бит.

#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))

Если n > 32,то результат равен нулю.

Функции

void MD5Init ( MD5_CTX *mdContext)

Функция MD5Init(MD5_CTX *mdContext) выполняет инициализацию некоторых полей структуры Message Digest MD5_CTX В качестве параметра функция получает указатель на структуру MD5_CTX.

{

/* Обнуление полей, которые будут содержать длину сообщения */

mdContext->i[0] = mdContext->i[1] = (UINT4)0;

/* Загрузка магических констант инициализации. */

mdContext->buf[0] = (UINT4)0x67452301L;

mdContext->buf[1] = (UINT4)0xefcdab89L;

mdContext->buf[2] = (UINT4)0x98badcfeL;

mdContext->buf[3] = (UINT4)0x10325476L;

}

void MD5Update (register MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen)

Данная функция обрабатывает содержимое структуры MD5_CTX.

В качестве параметров функция получает:

Указатель mdContext на структуру MD5_CTX;

Cимвольный буфер inBuf[],который содержит символы исходного сообщения,чей Message Digest мы подсчитываем; Длину inLen передаваемого буфера.

Вначале подсчитывается целочисленная величина mdi:

mdi = (int)((mdContext->i[0] >> 3) & 0x3F);

Эта величина равна длине сообщения в байтах по модулю 64.Длина сообщения в битах хранится в структуре MD5_CTX в буфере i[0 1].

Длина сообщения в битах заносится в буфер i[0 1] следующим образом:

mdContext->i[0] += ((UINT4)inLen << 3);

mdContext->i[1] += ((UINT4)inLen >> 29);

Следующий участок кода выполняет следующие действия:

while (inLen--)

{

/* добавляем новый символ в буфер, инкрементируя mdi */

mdContext->in[mdi++] = *inBuf++;

/* Если необходимо выполняем преобразование */

if (mdi == 0x40)

{

for (i = 0, ii = 0; i < 16; i++, ii += 4)

in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |

(((UINT4)mdContext->in[ii+2]) << 16) |

(((UINT4)mdContext->in[ii+1]) << 8) |

((UINT4)mdContext->in[ii]);

Transform (mdContext->buf, in);

mdi = 0;

}

}

Пока уменьшаемая на 1 длина переданного в функцию сообщения не станет равной нулю выполняем следующие действия:

Заносим новый символ из входного буфера функции в 64-х байтный буфер структуры MD5_CTX,увеличивая при этом переменную mdi на 1. Если mdi равна 64, то преобразуем

однобайтные символы буфера in[] стуктуры MD5_CTX в 4-х байтные величины типа UINT4, заносим в промежуточный буфер на 16 величин типа UINT4, и далее передаем функции Transform().Присваиваем переменной mdi 0.

void MD5Final (MD5_CTX *mdContext)

Функция завершает вычисление Message Digest и заносит полученное значение в структуре MD5_CTX в символьный буфер digest[0 .15].

Входным параметром функции является указатель на структуру MD5_CTX.

Основные моменты:

Расширение сообщения дополнительными заполняющими символами из таблицы PADDING[]

/* Подсчет длины сообщения в байтах по модулю 64 */

mdi = (int)((mdContext->i[0] >> 3) & 0x3F);

/* Расширить до 56 по модулю 64 */

padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);

MD5Update(mdContext, PADDING, padLen);

Присоединение битов длины и вызов функции Transform().

in[14] = mdContext->i[0];

in[15] = mdContext->i[1];

for (i = 0, ii = 0; i < 14; i++, ii += 4)

in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |

(((UINT4)mdContext->in[ii+2]) << 16) |

(((UINT4)mdContext->in[ii+1]) << 8) |

((UINT4)mdContext->in[ii]);

Transform (mdContext->buf, in);

Сохранение буфера в digest(т.е.получение окончательного Message Digest):

for (i = 0, ii = 0; i < 4; i++, ii += 4)

{

mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);

mdContext->digest[ii+1] = (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);

mdContext->digest[ii+2] = (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);

mdContext->digest[ii+3] = (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);

}

void Transform(register UINT4 *buf,register UINT4 *in)

Данная функция является основным шагом в алгоритме MD5.

Входными параметрами являются указатель на буфер buf[] из структуры MD5_CTX и указатель на буфер in[], хранящем значения типа UINT4. Функция выполняет 4 цикла по 16 шагов в каждом. В каждом цикле используется одна из функций FF, GG, HH, II. Далее окончательный результат после 64-х преобразовательных итераций добавляется к содержимому буфера buf[].

Структура MD5_CTX

Структура MD5_CTX является основной структурой для формирования MessageDigest. Структура содержит следующие поля:

typedef struct

{

UINT4 i[2]; /* количество бит в сообщении по mod 2^64 */

UINT4 buf[4]; /* временный буфер */

unsigned char in[64]; /* входной буфер */

unsigned char digest[16]; /* содержит действительный Message Digest

после вызова MD5Final() */

} MD5_CTX;

Цифровая подпись и криптосистемы с ключом общего пользования.

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

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

Используя этот ключ, Сэм шифрует документ и отправляет его Тому. Том дешифрует документ с помощью своего личного ключа. Это единственный ключ, с помощью которого можно восстановить документ, зашифрованный с применением ключа общего пользования, принадлежащего Тому. Тот факт, что ключ общего пользования Тома может стать кому-то известен, не имеет особого значения, потому что он абсолютно бесполезен для расшифровки документа. А личный ключ, известный одному лишь Тому, по открытым линиям связи не передавался; теоретически том хранит его только в собственной памяти и наоборот, работа других криптосистем с ключом общего пользования строится на обратном принципе: Сэм шифрует документ с помощью своего личного ключа и передает свой ключ общего пользования Тому, с помощью которого тот мог бы расшифровать этот документ. Существующие ныне криптосистемы с ключом общего пользования, такие, например, как система RSA (сокращение, составленное из первых букв фамилий трех создателей этого алгоритма), широко используются.


Страница: