Міністерство освіти та науки України
Національний університет „Львівська політехніка”
Кафедра ЕОМ
Звіт
з лабораторної роботи № 2
з курсу: « Проектування комп’ютерних засобів захисту»
на тему: “ Формування цифрового підпису згідно стандарту DSS”
Львів 2007
Мета роботи: реалізувати демонстраційну програму формування цифрового підпису вхідного повідомлення згідно стандарту DSS.
Теоретичні відомості
Відправник і отримувач електронного документа використовують при обчисленні великі цілі числа: і – прості числа, біт кожне ; – просте число довжиною 160 розрядів (дільник числа). Числа , , є відкритими і можуть бути спільними для всіх користувачів мережі.
Відправник вибирає випадкове ціле число (). Число – секретний ключ відправника для формування електронного цифрового підпису.
Наступним кроком відправник обчислює значення
.
Число – відкритий ключ для перевірки підпису відправника. Це число передається всім отримувачам документів.
Для того, щоб підписати документ , відправник хешує його в ціле хеш-значення :
,
після цього відправник генерує випадкове ціле число при умові, що , і обчислює число :
.
Обчисливши число відправник обчислює за допомогою секретного ключа ціле число :
.
Пара чисел і утворюють цифровий підпис
під документом .
Таким чином, підписане повідомлення складається з трьох чисел .
Отримувач підписаного повідомлення перевіряє виконання умов
,
і відкидає підпис, якщо хоча б одна з умов не виконується.
Потім отримувач обчислює значення
,
хеш-значення
і числа
Після цього отримувач за допомогою відкритого ключа обчислює значення
і перевіряє виконання умови
.
Якщо умова виконується, тоді підпис під документом визнається отримувачем як справжній.
Можна строго математично довести , що рівність буде виконуватися тоді і тільки тоді, коли підпис під документом отриманий за допомогою того секретного ключа , з якого був обчислений відкритий ключ . Таким чином, можна твердо переконатися , що відправник повідомлення володіє даним секретним ключом (не розкриваючи при цьому значення ключа ) і що відправник підписав даний документ .
Лістинг програми
int DSS_Setup()
{
FILE *fp;
big p,q,h,g,n,s,t;
miracl *mip=mirsys(100,0);
p=mirvar(0);
q=mirvar(0);
h=mirvar(0);
g=mirvar(0);
n=mirvar(0);
s=mirvar(0);
t=mirvar(0);
/* randomise */
/*
printf("Enter 9 digit random number seed = ");
scanf("%ld",&seed);
getchar();*/
seed=123456789;
irand(seed);
/* generate q */
forever
{
bigbits(QBITS,q);
nxprime(q,q);
if (logb2(q)>QBITS) continue;
break;
}
printf("q= ");
cotnum(q,stdout);
/* generate p */
expb2(PBITS,t);
decr(t,1,t);
premult(q,2,n);
divide(t,n,t);
expb2(PBITS-1,s);
decr(s,1,s);
divide(s,n,s);
forever
{
bigrand(t,p);
if (compare(p,s)<=0) continue;
premult(p,2,p);
multiply(p,q,p);
incr(p,1,p);
copy(p,n);
if (isprime(p)) break;
}
printf("p= ");
cotnum(p,stdout);
/* generate g */
do {
decr(p,1,t);
bigrand(t,h);
divide(t,q,t);
powmod(h,t,p,g);
} while (size(g)==1);
printf("g= ");
cotnum(g,stdout);
fp=fopen("common.dss","wt");
fprintf(fp,"%d\n",PBITS);
mip->IOBASE=16;
cotnum(p,fp);
cotnum(q,fp);
cotnum(g,fp);
fclose(fp);
/*clrscr();
ShowMenu();*/
return 0;
}
int DSS_GenerateKeys()
{
FILE *fp;
big p,q,g,x,y;
long seed;
int bits;
miracl *mip;
/* get common data */
fp=fopen("common.dss","rt");
if (fp==NULL)
{
printf("file common.dss does not exist\n");
return 0;
}
fscanf(fp,"%d\n",&bits);
mip=mirsys(bits/4,16); /* use Hex internally */
p=mirvar(0);
q=mirvar(0);
g=mirvar(0);
x=mirvar(0);
y=mirvar(0);
innum(p,fp);
innum(q,fp);
innum(g,fp);
fclose(fp);
/* randomise */
// printf("Enter 9 digit random number seed (for KEY generation) = ");
// scanf("%ld",&seed);
// getchar();
irand(seed);
powmod(g,q,p,y);
if (size(y)!=1)
{
printf("Problem - generator g is not of order q\n");
exit(0);
}
/* generate public/private keys */
bigrand(q,x);
powmod(g,x,p,y);
printf("public key = ");
otnum(y,stdout);
fp=fopen("public.dss","wt");
otnum(y,fp);
fclose(fp);
fp=fopen("private.dss","wt");
otnum(x,fp);
fclose(fp);
mirexit();
/*clrscr();
ShowMenu();*/
return 0;
}
void strip(char *name)
{ /* strip off filename extension */
int i;
for (i=0;name[i]!='\0';i++)
{
if (name[i]!='.') continue;
name[i]='\0';
break;
}
}
void hashing(FILE *fp,big hash)
{ /* compute hash function */
char h[20];
int i,ch;
sha sh;
shs_init(&sh);
while ((ch=fgetc(fp))!=EOF) shs_process(&sh,ch);
shs_hash(&sh,h);
bytes_to_big(20,h,hash);
}
int DSS_Verify()
{
FILE *fp;
char ifname[50],ofname[50];
big p,q,g,y,v,u1,u2,r,s,hash;
int bits;
miracl *mip;
/* get public data */
fp=fopen("common.dss","rt");
if (fp==NULL)
{
printf("file common.dss does not exist\n");
return 0;
}
fscanf(fp,"%d\n",&bits);
mip=mirsys(bits/4,16); /* Use Hex Internally */
p=mirvar(0);
q=mirvar(0);
g=mirvar(0);
y=mirvar(0);
v=mirvar(0);
u1=mirvar(0);
u2=mirvar(0);
s=mirvar(0);
r=mirvar(0);
hash=mirvar(0);
innum(p,fp);
innum(q,fp);
innum(g,fp);
fclose(fp);
/* get public key of signer */
fp=fopen("public.dss","rt");
if (fp==NULL)
{
printf("file public.dss does not exist\n");
return 0;
}
innum(y,fp);
fclose(fp);
/* get message */
//printf("signed file = ");
//gets(ifname);
//scanf("%s", ifname);
strcpy(ifname,"marichka.txt");
strcpy(ofname,ifname);
strip(ofname);
strcat(ofname,".dss");
if ((fp=fopen(ifname,"rb"))==NULL)
{ /* no message */
printf("Unable to open file %s\n",ifname);
return 0;
}
hashing(fp,hash);
fclose(fp);
fp=fopen(ofname,"rt");
if (fp==NULL)
{ /* no signature */
printf("signature file %s does not exist\n",ofname);
return 0;
}
innum(r,fp);
innum(s,fp);
fclose(fp);
if (compare(r,q)>=0 || compare(s,q)>=0)
{
printf("Signature is NOT verified\n");
return 0;
}
xgcd(s,q,s,s,s);
mad(hash,s,s,q,q,u1);
mad(r,s,s,q,q,u2);
powmod2(g,u1,y,u2,p,v);
divide(v,q,q);
if (compare(v,r)==0) printf("Signature is verified\n");
else printf("Signature is NOT verified\n");
return 0;
}
int DSS_Sign()
{
FILE *fp;
char ifname[50],ofname[50];
big p,q,g,x,r,s,k,hash;
long seed;
int bits;
miracl *mip;
printf("File to sign is 'marichka.txt'\n");
DSS_Setup() ;
DSS_GenerateKeys();
/* get public data */
fp=fopen("common.dss","rt");
if (fp==NULL)
{
printf("file common.dss does not exist\n");
return 0;
}
fscanf(fp,"%d\n",&bits);
mip=mirsys(bits/4,16); /* use Hex internally */
p=mirvar(0);
q=mirvar(0);
g=mirvar(0);
x=mirvar(0);
r=mirvar(0);
s=mirvar(0);
k=mirvar(0);
hash=mirvar(0);
innum(p,fp);
innum(q,fp);
innum(g,fp);
fclose(fp);
/* randomise */
//printf("Enter 9 digit random number seed = ");
//scanf("%ld",&seed);
//getchar();
irand(seed);
/* calculate r - this can be done offline,
and hence amortized to almost nothing */
bigrand(q,k);
powmod(g,k,p,r); /* see brick.c for method to speed this up */
divide(r,q,q);
/* get private key of signer */
fp=fopen("private.dss","rt");
if (fp==NULL)
{
printf("file private.dss does not exist\n");
return 0;
}
innum(x,fp);
fclose(fp);
/* calculate message digest */
//printf("file to be signed = ");
//gets(ifname);
//scanf("%s", ifname);
strcpy(ifname,"lab_2_3_dss.txt");
strcpy(ofname,ifname);
strip(ofname);
strcat(ofname,".dss");
if ((fp=fopen(ifname,"rb"))==NULL)
{
printf("Unable to open file %s\n",ifname);
return 0;
}
// calculates SHA hash
hashing(fp,hash);
fclose(fp);
/* calculate s */
xgcd(k,q,k,k,k);
mad(x,r,hash,q,q,s);
mad(s,k,k,q,q,s);
fp=fopen(ofname,"wt");
otnum(r,fp);
otnum(s,fp);
fclose(fp);
mirexit();
//clrscr();
//ShowMenu();
printf("File signed\n");
DSS_Verify();
return 0;
}
Результати роботи програми
Висновок: в результаті виконання лабораторної роботи було реалізовано демонстраційну програму формування цифрового підпису вхідного повідомлення згідно стандарту DSS.