#include <cstring> #include <iostream> Class DSA { Public: Big p, q,..." />

Програмний код для алгоритму ЕЦП ЕЦП DSS/DSА - Розробка електронного цифрового підпису

#include "stdafx. h"

Extern "C"

{

#include "miracl. h"

}

#include <ctime>

#include <cstring>

#include <iostream>

Class DSA

{

Public:

Big p, q, g; // открытые параметры алгоритма

Csprng rng; // криптографический стойкий генератор ПСЧ

Void sign(void *msg, int len, big x, big r, big s); // подпись

Bool check(void *msg, int len, big y, big r, big s); // проверка

Void genKeys(big x, big y); // генерация ключевой пары

Void genOpenParams(char *seed, int len); // генерация открытых

Параметров

DSA(char *seed, int len);

~DSA();

};

// здесь во всю используется бблиотека miracl, big -- число большой

Разрядности

Inline void sha_string(char* msg, int len, char* tmp) // хеширование в

Строку

{

Sha sha; // sha1 хеш

Shs_init(&;sha); // инициализация

For (int i = 0; i < len; i++)

Shs_process(&;sha, msg[i]); // хешируем сообщение

Shs_hash(&;sha, tmp); // записываем результат в выходной буфер

}

Inline void sha_string(char* msg, int len, big t) // хеширование в big число

{

Char tmp[20];

Sha_string(msg, len, tmp); // хешируем в строку

Bytes_to_big(20, tmp, t); // преобразуем строку в число

}

Inline void inc(char *seed, int len) // увеличиваем seed на 1, используется

При генерации открытых параметров

{

Seed[len - 1]++; // инкрементируем младший байт

For (int i = len - 2; i >= 0; i--) // идем начиная с предпоследнего

{

If (seed[i + 1] == 0) // если байт 0 -- считаем что произошло

Переполнение

Seed[i]++; // и увеличиваем старший байт на один

Else

Break; // при первом отсутствии переполнения выходим из цикла

}

}

DSA::DSA(char *seed, int len)

{

Strong_init(&;rng, len, seed, time(NULL)); // инициализация генератора

ПСЧ

}

DSA::~DSA()

{

Mirkill(p); // освобождаем память

Mirkill(q);

Mirkill(g);

}

Void DSA::sign(void *msg, int len, big x, big r, big s)

{

Big k = mirvar(0); // раундовый ключ

Big t = mirvar(0); // временная переменная

Strong_bigrand(&;rng, q, k); // заполняем k случайным числом меньшим q

Powmod(g, k, p, r); // вычисляем r по модулю p

Divide(r, q, q); // теперь берем по модулю q

Sha_string((char*)msg, len, t); // хешируем сообщение

Multiply(x, r, s); // расчет s

Add(s, t, s);

Divide(s, q, q);

Xgcd(k, q, k, k, k); // поиск обратного элемента

Multiply(s, k, s);

Divide(s, q, q);

Mirkill(k); // подчищаем

Mirkill(t);

}

Bool DSA::check(void *msg, int len, big y, big r, big s)

{

Big w = mirvar(0), u1 = mirvar(0), u2 = mirvar(0), v = mirvar(0);

Copy(s, w);

Xgcd(w, q, w, w, w); // w=1/s

Sha_string((char*)msg, len, u1); // хешируем

Multiply(u1, w, u1); // домножаем

Multiply(r, w, u2);

Powmod2(g, u1, y, u2, p, v); // двойное возведение в степень,

V=g^u1*y^u2 mod p

Divide(v, q, q); // приводим по модулю q

Bool res = !compare(v, r); // compare вернет 0 при совпадении

Переменных

Mirkill(w); mirkill(u1); mirkill(u2); mirkill(v);

Return res;

}

Void DSA::genKeys(big x, big y)

{

Strong_bigrand(&;rng, q, x); // случайных закрытый ключ

Powmod(g, x, p, y); // открытый

}

Void DSA::genOpenParams(char *seed, int len) // стр 11 fips 186-1

{

P = mirvar(0);

Q = mirvar(0);

G = mirvar(0);

Do

{

// step 2

Char u[20];

Sha_string(seed, len, u); //певый операнд в u

Inc(seed, len); // seed = seed + 1

Char t[20];

Sha_string(seed, len, t); // второй операнд

For (int i = 0; i < 20; i++) // xor

U[i] ^= t[i];

//step 3

U[0] |= 1;

U[len - 1] |= 1 << 7;

Bytes_to_big(20, u, q); // переводим массив байт в число

} while (!isprime(q)); // step 4

Big X = mirvar(0);

Big t = mirvar(1);

Sftbit(t, 1023, t); // t=2^(L-1)

Do

{

Inc(seed, len); // вместе с первым inc в следующем цикле образует

Offset=2

Char V[1024 / 8];

Char *ptr = V; // указатель на Vk

For (int k = 0; k < 1024 / 160; k++) // step 7

{

Inc(seed, len); // seed += 1

Sha_string(seed, len, ptr); // Vk=SHA1(seed+offset+k)

Ptr += 20; // по сути K++, переход к следующей части буфера

}

Bytes_to_big(sizeof(V), V, X); // step 8

Add(X, t, X); // в t 2^(L-1)

//step 9

Sftbit(q, 1, q); // q=2q, побитовый сдвиг

Copy(X, t); // t=X

Divide(t, q, q); // t=X mod 2q, в документации это c

Sftbit(q, -1, q); // q=2q/2=q

Decr(t, 1, t); // c-1

Subtract(X, t, p); // p=X-(c-1)

Convert(1, t); // востанавливаем 2^(L-1) в t

Sftbit(t, 1023, t);

If (compare(p, t) == -1) // step 10

Goto loopend;

If (isprime(p))

Break; // если p простое -- выходим из цикла

Loopend:

Inc(seed, len); // по сути offset+=1

} while (true);

Copy(p, X); // X=p

Decr(X, 1, X); // X=p-1

Copy(q, t); // t=q

Xgcd(t, p, t, t, t); //t=1/q

Multiply(X, t, X); // X=(p-1)/q

Divide(X, p, p); // X=(p-1)/q mod p, в документации на 7 стр, степень при

H

Do

{

Bigrand(q, t);// по сути t=h

Powmod(t, X, p, g); // генерация g=h^((p-1)/q) mod p

} while (size(g) == 1); // пока g=1

Mirkill(X);

Mirkill(t);

}

Template<typename Signature>

Void test(char *msg, char *alg) // тест подписи

{

Char seed[20] = { 1, 2, 3, 4, 5, 6, 7 }; // зерно

Signature sign(seed, sizeof(seed));

Sign. genOpenParams(seed, sizeof(seed)); // генерация открытых

Параметров

Big x = mirvar(0), y = mirvar(0); // ключи

Sign. genKeys(x, y); // их генерация

Std::cout << "Testing " << alg << ": " << std::endl;

Big r = mirvar(0), s = mirvar(0); // подпись

Sign. sign(msg, strlen(msg), x, r, s); // подписываем

Std::cout << "Sing: ";

Char num[1000];

Cotstr(r, num); // функция, конвертирующая big в строку, часть miracl

Std::cout << num << std::endl;

Cotstr(s, num);

Std::cout << num << std::endl;

If (sign. check(msg, strlen(msg), y, r, s)) // проверяем подпись

Std::cout << "Sign match" << std::endl;

Else

Std::cout << "Sign mismatch" << std::endl;

Msg[0] ^= 1; // меняем сообщение

Std::cout << "Changing msg... msg: " << msg << ": ";

If (sign. check(msg, strlen(msg), y, r, s)) // проверяем отклонение подписи

Std::cout << "Sign match" << std::endl;

Else

Std::cout << "Sign mismatch" << std::endl;

Msg[0] ^= 1; // востанавлдиваем сообщение

Incr(r, 1, r); // и портим подпись

Std::cout << "Restoring msg and changing r: ";

If (sign. check(msg, strlen(msg), y, r, s)) // проверяем отклонение подписи

Std::cout << "Sign match" << std::endl;

Else

Std::cout << "Sign mismatch" << std::endl;

}

Int _tmain(int argc, _TCHAR* argv[])

{

Mirsys(64 * 3, 0)->IOBASE = 16; // инициализируем miracl, ввод-вывод в

16й системе

Char msg[1024]; // сообщение

Std::cout << "Enter msg:> ";

Std::cin. getline(msg, sizeof(msg));

Test<DSA>(msg, "DSA"); // тестируем DSA

System("pause");

Return 0;

}

Похожие статьи




Програмний код для алгоритму ЕЦП ЕЦП DSS/DSА - Розробка електронного цифрового підпису

Предыдущая | Следующая