/* * C Diffie-Hellman implementacija koristeci GNU MP biblioteku * Dinko Korunic, 0036355514 * * Copyright (C) 2002 Dinko Korunic * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Seminar 2. iz predmeta Operacijski sustavi 2 * Literatura: * - Ritter's Crypto Glossary and Dictionary of Technical Cryptography * - RFC2631 (Diffie-Hellman Key Agreement Method, June 1999, E. Rescorla) * - Diffie-Hellman Key Exchange (Alan Westrope, 1998) * - izvorni programi: Diffie-Hellman key exchange, using CypherMath8 * (Win32 C); Diffie-Hellman key exchange od Jeff Williams (x86 Asm + C) */ /* * Diffie-Hellman metoda razmjene kljuceva * - sluzi za stvaranje tajnog kljuca i razmjenu izmedju dva racunala * (osobe, hosta, itd.) * - formalni postupak: * 1) dobivanje DH parametara: prim broj odnosno modul `p' (veci od 2) i * baza `g' koji je cijeli broj manji od p; oni mogu biti * hardkodirani ili dohvaceni sa kakvog posluzitelja * 2) svaki host tajno generira privatni broj `x' koji je manji od p - 1 * 3) svaki host generira javni kljuc `y' pomocu funkcije: * y = g ^ x % p * 4) nakon toga se doticna dva hosta izmijene javne kljuceve (`y') i * oni su pretvoreni u tajni broj `z' funkcijom: * z = y ^ x % p * - sada se `z' moze koristiti za bilo kakav enkripcijski algoritam i * razmjenu podataka izmedju posluzitelja; matematicki, ova dva hosta bi * trebali imati istu vrijednost `z': * z = (g ^ x % p) ^ x' % p = (g ^ x' % p) ^ x % p * - naravno, svi navedeni brojevi su pozitivni cijeli brojevi */ #include #include #include #include #include #include mpz_t base_g, modulus_g; gmp_randstate_t state_g; /* * Postavljanje DH parametara (baza i modul) u globalne parametre * Ulaz: lokacija baze (lokalno) i modula (lokalno) * Izlaz: -1 ako su baza i modul 0, -2 ako baza nije manja od modula, 0 * ako je sve OK */ int dh_setparms(mpz_t *base, mpz_t *modulus) { /* provjeri jesu li slucajno 0 */ if (!mpz_sgn(*base) || !mpz_sgn(*modulus)) return -1; /* baza je MANJA od modula! */ if (mpz_cmp(*base, *modulus) >= 0) return -2; /* inicijaliziraj i podesi globalnu bazu i modul */ mpz_init(base_g); mpz_init(modulus_g); mpz_set(base_g, *base); mpz_set(modulus_g, *modulus); gmp_printf("Postavio bazu = %Zd\n", base_g); gmp_printf("Postavio modulus = %Zd\n", modulus_g); return 0; } /* * Generiranje javnog DH kljuca koji se salje udaljenom hostu.. * Ulaz: lokacija za tajni kljuc, lokacija za javni kljuc * Izlaz: nista :-) */ void dh_genpublic(mpz_t *secret, mpz_t *public) { /* inicijaliziraj */ mpz_init(*secret); mpz_init(*public); /* generira se slucajni x s time da x < (p - 1) */ mpz_urandomm(*secret, state_g, modulus_g); gmp_printf("Izracunao privatni broj = %Zd\n", *secret); /* generira se javni kljuc y sa y = g ^ x % p */ mpz_powm(*public, base_g, *secret, modulus_g); gmp_printf("Izracunao javni kljuc = %Zd\n", *public); } /* * Generiranje tajnog DH kljuca (nuzno je znati javni kljuc generiran od * strane udaljenog hosta) * Ulaz: lokacija primljenog javnog kljuca, vlastiti privatni broj, * lokacija za izracunati tajni kljuc (simetricni kljuc) */ void dh_genprivate(mpz_t *public, mpz_t *secret, mpz_t *private) { /* inicijaliziraj */ mpz_init(*private); /* racuna se tajni broj z = y ^ x % p */ mpz_powm(*private, *public, *secret, modulus_g); gmp_printf("Izracunao privatni kljuc = %Zd\n", *private); } int main(void) { /* potrebni MP cjelobrojni tipovi */ mpz_t base, modulus; mpz_t bobpub, bobsec, bobpri; mpz_t alicepub, alicesec, alicepri; /* inicijaliziraj */ mpz_init(base); mpz_init(modulus); /* podesi bazu na hardkodirani broj */ mpz_set_str(base, "0x2344010023498019329fafef32324ff65f22398490001291209291", 0); /* podesi modul na hardkodirani prim broj */ mpz_set_str(modulus, "0x0113f7fefd73f9d36ff3fefd2e34102202d01022d0c4410113f7fefc1400000014000003e3f3fefd43fbfefc12cc102062cc102063f7fefecc300d0013", 0); /* provjeri da li je modul prim broj */ if (!mpz_probab_prime_p(modulus, 15)) { fputs("Modulus nije prim broj\n", stderr); exit(EXIT_FAILURE); } /* podesi DH parametre */ if (dh_setparms(&base, &modulus) < 0) { fputs("Greska u podesavanju DH parametara\n", stderr); exit(EXIT_FAILURE); } /* inicijaliziraj PRNG */ gmp_randinit_lc_2exp_size(state_g, 128); gmp_randseed_ui(state_g, time(NULL) + getpid()); /* generiraj parove javni i tajni kljuc */ puts("Generiram Bobov javni kljuc"); dh_genpublic(&bobsec, &bobpub); puts("Generiram Alicin javni kljuc"); dh_genpublic(&alicesec, &alicepub); puts("Generiram Alicin tajni kljuc"); dh_genprivate(&bobpub, &alicesec, &alicepri); puts("Generiram Bobov tajni kljuc"); dh_genprivate(&alicepub, &bobsec, &bobpri); /* provjeri jesu li tajni kljucevi isti - simetricni? */ printf("Bobov i Alicin kljuc su %s!\n", mpz_cmp(alicepri, bobpri) ? "*razliciti*" : "*isti*"); /* ocisti sve */ gmp_randclear(state_g); mpz_clear(base_g); mpz_clear(modulus_g); mpz_clear(base); mpz_clear(modulus); mpz_clear(bobpub); mpz_clear(bobsec); mpz_clear(bobpri); mpz_clear(alicepub); mpz_clear(alicesec); mpz_clear(alicepri); return EXIT_SUCCESS; }