Rapport Semesteroppgave i datasikkerhet Harald Dahle (795955) og Joakim L. Gilje (796196)



Like dokumenter
1 ØVING I WINDOWS FRA CHRISTIAN ANDOLO

Del 1 En oversikt over C-programmering

Oversikt. Introduksjon Kildekode Kompilering Hello world Hello world med argumenter. 1 C programmering. 2 Funksjoner. 3 Datatyper. 4 Pekere og arrays

HØGSKOLEN I SØR-TRØNDELAG Avdeling for informatikk og e-læring - AITeL

INF1040 Oppgavesett 14: Kryptering og steganografi

Steg 1: Regneoperasjoner på en klokke

Database security. Kapittel 14 Building Secure Software. Inf329, Høst 2005 Isabel Maldonado

TDT4102 Prosedyre og Objektorientert programmering Vår 2014

Kapittel 1 En oversikt over C-språket

Programmering i C++ Løsningsforslag Eksamen høsten 2005

Lynkurs i shellprogrammering under Linux

Kryptering Kongruensregning Kongruensregning i kryptering Litteratur. Hemmelige koder. Kristian Ranestad. 9. Mars 2006

TDT4102 Prosedyre og Objektorientert programmering Vår 2015

Kanter, kanter, mange mangekanter

Algoritmer og Datastrukturer

TOD063 Datastrukturer og algoritmer

TDT4102 Prosedyreog objektorientert programmering Vår 2016

Oppgaver til kapittel 19 - Kryptering og steganografi

Steg 1: Rest etter divisjon

TDT4102 Prosedyreog objektorientert programmering Vår 2016

En oppsummering (og litt som står igjen)

Oppgavene 1, 2, 4, 5, 6, 9, 12 og 13 passer best til å løses ved en datamaskin.

Del 4 Noen spesielle C-elementer

IN 147 Program og maskinvare

Løsningsforslag EKSAMEN

EKSAMENSOPPGAVE. INF-1100 Innføring i programmering og datamaskiners virkemåte. Ingen. Elektronisk (WiseFlow) Robert Pettersen

Offentlig nøkkel kryptografi og RSA

Algoritmer - definisjon

Kryptering med vigenere-metoden

Nybegynnerkurs i C. Øyvind Grønnesby. 14. oktober Introduksjon Typer Operatorer Kontrollstrukturer Pekere Makroer Lenker

INF1010 notat: Binærsøking og quicksort

INF Seminaroppgaver til uke 3

Hash-funksjoner. Introduksjon. Steg 1: Strekkoder. Eksempel. Skrevet av: Martin Strand

Skilpaddefraktaler Erfaren Python PDF

<?php. count tar en array som argument, og returnerer et tall som uttrykker antallet innførsler i arrayen.

Matematikk Øvingsoppgaver i numerikk leksjon 8 Matriser. Løsningsforslag

Løsningsforslag Øving 5 TMA4140 Diskret matematikk Høsten 2010

Løse reelle problemer

Ordliste. Obligatorisk oppgave 1 - Inf 1020

Utførelse av programmer, metoder og synlighet av variabler i JSP

Sikkerhet i GSM mobilteleforsystem

Universitetet i Bergen Det matematisk-naturvitenskapelige fakultet Institutt for informatikk

Øvingsforelesning 3 Python (TDT4110)

Populærvitenskapelig foredrag Kryptering til hverdag og fest

Algoritmer og datastrukturer Kapittel 9 - Delkapittel 9.2

Client-side Security

LØSNINGSFORSLAG SIF5015 DISKRET MATEMATIKK Onsdag 18. desember 2002

Algoritmer og datastrukturer Kapittel 11 - Delkapittel 11.2

TDT4105 Informasjonsteknologi grunnkurs: Uke 42 Strenger og strenghåndtering

Kryptogra og elliptiske kurver

Løsningsforslag til eksamen 24. november 2015

Algoritmer og datastrukturer Kapittel 1 - Delkapittel 1.3

HØGSKOLEN I SØR-TRØNDELAG Avdeling for informatikk og e-læring - AITeL

Oversikt over kryptografi

Introduksjon til objektorientert. programmering. Hva skjedde ~1967? Lokale (og globale) helter. Grunnkurs i objektorientert.

Algoritmer og datastrukturer Kapittel 1 - Delkapittel 1.8

MAT1030 Diskret matematikk

TDT4102 Prosedyreog objektorientert programmering Vår 2016

Dagens tema: 12 gode råd for en kompilatorskriver. Sjekking av navn. Lagring av navn. Hvordan finne et navn?

BOKMÅL Side 1 av 5. KONTERINGSEKSAMEN I FAG TDT4102 Prosedyre og objektorientert programmering. Onsdag 6. august 2008 Kl

Algoritmeanalyse. (og litt om datastrukturer)

E K S A M E N. Grunnleggende datakunnskap og programmering 98HINDA / 98HINDB / 98HINEA 98HDMUA / 98HDMUB / 98HINGA

Algoritmer og datastrukturer Kapittel 9 - Delkapittel 9.1

Kryptering med Vigenère-metoden

KONTINUASJONSEKSAMEN

Oppgave 1 a. INF1020 Algoritmer og datastrukturer. Oppgave 1 b

IN 147 Program og maskinvare

INF1000 Metoder. Marit Nybakken 16. februar 2004

Mer om C programmering og cuncurrency

EKSAMEN. Algoritmer og datastrukturer. Eksamensoppgaven: Oppgavesettet består av 11 sider inklusiv vedlegg og denne forsiden.

Programmeringsspråket C

Løsningsforslag for eksamensoppgave, våren 2004

På tide med et nytt spill! I dag skal vi lage tre på rad, hvor spillerne etter tur merker ruter med X eller O inntil en av spillerne får tre på rad.

Repetisjon Novice Videregående Python PDF

HØYSKOLEN I OSLO, AVDELING FOR INGENIØRUTDANNING

Løsningsforslag ukeoppg. 9: okt (INF Høst 2011)

TDT4105 IT Grunnkurs Høst 2014

Kontinuasjonseksamen

TDT4102 Prosedyre og Objektorientert programmering Vår 2014

QED 1 7. Matematikk for grunnskolelærerutdanningen. Bind 2. Fasit kapittel 1 Tallenes hemmeligheter

Høgskolen i Gjøvik Institutt for informatikk og medieteknikk E K S A M E N. Grunnleggende programmering

LITT OM OPPLEGGET. INF1000 EKSTRATILBUD Stoff fra uke September 2012 Siri Moe Jensen EKSEMPLER

KAPITTEL 3 Litt logikk og noen andre småting

Administrivia INF 3110/ INF /02/2005 1

EKSAMENSOPPGAVE. INF-1100 Innføring i programmering og datamaskiners virkemåte. Teorifagb, hus 3, og og Adm.bygget, Aud.max og B.

Matematikk Øvingsoppgaver i numerikk leksjon 5 Skript

static int ant_steiner; //antall steiner static int teller2 = 0; //teller for printing til Thread^ murer; //murertråden

EKSAMEN. Operativsystemer. 1. Læreboken "A Practical Guide to Red Hat Linux" av Mark Sobell 2. Maks. tre A-4 ark med selvskrevne notater.

INF oktober Dagens tema: Uavgjørbarhet. Neste uke: NP-kompletthet

Funksjonalitet og oppbygning av et OS (og litt mer om Linux)

ECC i akademia vs. industrien

Ny/utsatt EKSAMEN. Dato: 6. januar 2017 Eksamenstid: 09:00 13:00

Betinget eksekvering og logiske tester i shell

Kondisjonstest. Algoritmer og datastrukturer. Python-oppgaver. Onsdag 6. oktober Her er noen repetisjonsoppgaver i Python.

Tre på rad mot datamaskinen. Steg 1: Vi fortsetter fra forrige gang. Sjekkliste. Introduksjon

Kryptografi og nettverkssikkerhet

IN 147 Program og maskinvare

Diverse eksamensgaver

"Nelsons kaffebutikk"

UNIVERSITETET I OSLO

Transkript:

Rapport Semesteroppgave i datasikkerhet Harald Dahle (795955) og Joakim L. Gilje (796196) Sammendrag Oppgaven går ut på å implementere RSA-krypteringen. Deloppgaver for denne krypteringen er å implementere nøkkelgenerator, kryptering og dekryptering. Det å implementere en nøkkelgenerator for RSA-krypteringen krever igjen at det er tilgjengelig en funksjon for å finne primtall. Valg av verktøy Da offentlig-nøkkel kryptering involverer bruk av store tall (som går langt utover 32 og 64-bits), har det også vært bruk for funksjonalitet for å jobbe med så store tall. Vi anså det som langt utenfor rammene av oppgaven å implementere et slikt bibliotek. På grunn av dette valgte vi å se etter et bibliotek og funksjoner for å jobbe mot svært store tall fra en tredje part. Valget falt på libcrypto, som er en del av OpenSSL [1]. Dette ga oss også en fordel da hovedoppgaven til libcrypto er nettopp kryptering, og vi har hatt muligheten til å verifisere f.eks. primtallene funnet ved vår implementasjon mot OpenSSL. Oppgaven er programmert i C. Utenom libcrypto er det kun benyttet standard C funksjoner. Oppgaven er utviklet og testet på IRIX, Solaris, MacOS X og Linux. Om RSA RSA er en algoritme for kryptering og dekryptering. Spesielt for RSA i motsetning tradisjonelle krypteringsalgoritmer er at man har en offentlig og en privat nøkkel. Den offentlige nøkkelen kan gjøres tilgjengelig for resten av verden (også «skumle» mennesker), mens man må se til at den private nøkkelen holdes hemmelig. RSA nøkkelgenerering består i 5 steg: 1. finn to ulike primtall, p og q 2. finn produktet av p og q, n 3. finn totient, (p-1)(q-1) 4. finn e, hvor e er mindre enn totient og relativt primtall til totient 5. finn d, som er invers av e modulo totient Offentlig nøkkel består av e og n, mens privat nøkkel består av d og n. Kryptering består da av C=M e mod n, mens dekryptering består av M =C d mod n. Her er M meldingen i klartekst, mens C er den krypterte meldingen (cipher-tekst). Implementering av oppgaven For å lære implementasjonen av RSA, har vi brukt Wikipedia [2] og Cryptography and Network Security [3]. Det å generere RSA nøkler krever i tillegg implementering av «Modular Exponentiation», «MillerRabin-test» og «Extended Euclidean Greatest Common Divisor». Her har vi fått hjelp av Wikipedia [4][5], Cryptography and Network Security [6], samt Algorithm Design [7]. RSA kryptering og dekryptering består kun av «Modular Exponentiation». «Modular Exponentiation» er regnestykker på følgende form: a b mod c. Årsaken til at man benytter en spesiell algoritme her, er for å slippe å regne ut a b som blir et nesten uendelig stort tall. I stedet «kortes» tallet hele tiden ned ved å trekke modulo-delen inn i regnestykket. «MillerRabin-test» er en algoritme for å sjekke om et tall kan være primtall. Dette er en av de største usikkerhetene ved hele nøkkelgenereringen da man aldri kan være sikker på at det er et primtall. For et tall n vil det kreve en sjekk på alle tall opp til n før man kan verifisere at n er et primtall. Da RSA-nøkler med størrelse på 2048 bit genereres ved to 1024-tall, blir det for mange tester å utføre i praksis. «MillerRabin-testen» vil istedet gi beskjed dersom det med sikkerhet kan

sies at tallet er faktoriserbart. For å minke sannsynligheten for å feilaktig godkjenne et faktoriserbart tall som et primtall, blir tallene testet 10 ganger. I gjennomsnitt skal man utføre 0.5 ln n søk [6]. «Extended Euclidean GCD» er en måte å regne ut den største felles nevner (GCD) mellom to tall. Det brukes under nøkkelgenerering under steg 4 og steg 5 (stegene er også angitt i kildekoden, under funksjonen generatekey(unsigned int)). I steg 4 ønsker en å sjekke at tallet e er relativt primtall til totienten, mens man i steg 5 ønsker å finne et tall d som tilfredstiller formelen de 1 mod totient. Begge deler kan finnes ved denne algoritmen, man må bare ta hensyn til hvilket tall som skal returneres fra funksjonen. Resultater Programmet er et enkelt kommandolinjebasert program. Man kan generere nøkler ved argumentet 'genkey' og ønsket bitlengde for nøkkelen. Programmet vil da generere et offentlig nøkkelpar og lagre offentlig nøkkel i filen pub, mens privat nøkkel lagres i priv. I tidligere versjoner av programmet ble libcrypto også brukt til å verifisere primtallene p og q under nøkkelgenerering. For å kryptere kaller man opp programmet med argumentet 'encrypt' samt hvilken nøkkel som skal brukes til krypteringen. Kryptert tekst lagres i filen cipher.txt. Tilsvarende for dekryptering kalles programmet med argumentet 'decrypt' samt hvilken nøkkel som skal brukes til dekrypteringen. Dekryptert tekst lagres i filen plain.txt. Programmet vil lese inn data fra stdin, og ofte er det enkleste på en Unix-plattform å bruke en «pipe»,, for å sende data inn til programmet. Eksempler på bruk # generering av et 2048-bits nøkkelpar./rsacrypt genkey 2048 # kryptere filen tekst cat tekst./rsacrypt encrypt mottakers-offentlige-nøkkel # dekryptere en mottatt fil mottatt-tekst cat mottatt-tekst./rsacrypt decrypt min-private-nøkkel Vi har verifisert «Modular Exponentiation», «Extended Euclidean GCD» og «Miller-Rabin test» mot implementasjoner som allerede eksisterer i OpenSSL, og fått bekreftet at disse fungerer korrekt. Begrensninger av implementeringen Når man krypterer en tekst blir den krypterte teksten lagret som en heksadesimal streng. Det betyr at den krypterte teksten bruker dobbel så stor plass som nødvendig. Under dekryptering blir den dekrypterte meldingen lagret som en streng, noe som forhindrer kryptering av binærer. Disse to tilfellene ville vært trivielle å forbedre, men vi ønsket ikke å komplisere oppgaven unødvendig. Vi har oppnådd hva vi ønsket. Konklusjon Programmet fungerer, og vi kan med sikkerhet si at programmet transformerer en klartekst til noe annet. Det er dessverre vanskelig for oss å verifisere en 2048-bits kryptering, men programmet har blitt testet ut fra blant annet eksempler gitt i boken med suksess.

Referanser [1] OpenSSL: http://www.openssl.org [2] Wikipedia artikkel om RSA: http://en.wikipedia.org/wiki/rsa [3] Cryptography and Network Security: kapittel 9 [4] Wikipedia artikkel om Miller-Rabin primtallstest: http://en.wikipedia.org/wiki/miller-rabin_primality_test [5] Wikipedia artikkel om Extended Euclidean algoritmen: http://en.wikipedia.org/wiki/extended_euclidean_algorithm [6] Cryptography and Network Security: Kapittel 8 [7] Algorithm Design: Kapittel 10.1 Koden vår ligger under CVS-kontroll på http://jgilje.net/cgi-bin/cvsweb/rsacrypt/.

Kildekode Revision 1.13, Thu Oct 27 12:29:17 2005 UTC CVS Tags: HEAD #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/bn.h> BIGNUM* one; BIGNUM* two; BN_CTX* BN_context; millerrabin-testen skal kjã res flere ganger derfor opprettes det et sett med BN som er felles for hvert kall typedef struct millerrabinbntemp { BIGNUM* d; BIGNUM* a; BIGNUM* tmp; BIGNUM* compare; BIGNUM* range; BIGNUM* testm1; BIGNUM* r; millerrabinbntemp; denne koden er presentert flerne steder... (bl.a. Figur 9.7, side 273 i CNS) b: base, e: exponent, m: modulus target: BN hvor resultatet lagres r: temp-verdi (raskere kalkulasjon nã r denne kjã res ofte) void modexponentiationbn(bignum* target, BIGNUM* b, BIGNUM* e, BIGNUM* m, BIGNUM* r) { int i; BN_set_word(target, 1); for (i = BN_num_bits(e); i >= 0; i--) { BN_mod_sqr(r, target, m, BN_context); if (BN_is_bit_set(e,i)) { BN_mod_mul(target, r, b, m, BN_context); else { BN_copy(target, r); return; initialiser innholdet i struct millerrabinbntemp void millerrabinbninit(millerrabinbntemp* bntemp) {

bntemp->d = BN_new(); bntemp->a = BN_new(); bntemp->tmp = BN_new(); bntemp->compare = BN_new(); bntemp->range = BN_new(); bntemp->testm1 = BN_new(); bntemp->r = BN_new(); rydd opp etter millerrabin-testen void millerrabinbnfree(millerrabinbntemp* bntemp) { BN_free(bnTemp->d); BN_free(bnTemp->a); BN_free(bnTemp->tmp); BN_free(bnTemp->compare); BN_free(bnTemp->range); BN_free(bnTemp->testM1); BN_free(bnTemp->r); Dette er en implementasjon av algoritmen presentert side 244 i CNS, og http://en.wikipedia.org/wiki/miller-rabin_primality_test test - nummer à teste (n i boka) times - antall ganger à test Miller-Rabin testen viser egentlig om et tall med sikkerhet kan faktoriseres. Derfor returnerer testen sann (1) hvis tallet test kan faktoriseres. int millerrabintestbn(bignum* test, unsigned int times, millerrabinbntemp* bntemp) { unsigned int twoexp = 0; unsigned int i, j; unsigned int ok = 0; BN_sub(bnTemp->testM1, test, one); BN_copy(bnTemp->d, bntemp->testm1); while (! BN_is_odd(bnTemp->d)) { twoexp++; BN_rshift1(bnTemp->d, bntemp->d); // selve testen for (i = 0; i < times; i++) { BN_rand_range(bnTemp->a, test); if (BN_is_zero(bnTemp->a)) BN_one(bnTemp->a); ok = 0; modexponentiationbn(bntemp->compare, bntemp->a, bntemp->d, test, bntemp->r); if (BN_is_one(bnTemp->compare)) { // printf("inconclusive on T1: modexponentiation(a, yarr, test) == 1\n"); continue;

for (j = 0; j < twoexp; j++) { BN_set_word(bnTemp->range, (unsigned long) j); BN_exp(bnTemp->tmp, two, bntemp->range, BN_context); BN_mul(bnTemp->tmp, bntemp->tmp, bntemp->d, BN_context); >tmp, test, bntemp->r); modexponentiationbn(bntemp->compare, bntemp->a, bntemp- if (! BN_cmp(bnTemp->compare, bntemp->testm1)) { // printf("inconclusive on T2: modexponentiation(a, pow(2, j) * yarr, test) == (test - 1)\n"); ok = 1; break; if (ok) continue; // printf("composite\n"); // printf("probably prime\n"); return 0; et ganske dã rlig funksjonsnavn... dette er en implementasjon av "extended euclidean algorithm" relprime: angir om man tester pã om man har funnet to relative primtall (steg 4 i RSA-keygen) void extgcdbn(bignum* target, BIGNUM* z, BIGNUM* x, int relprime) { BIGNUM *a, *b, *c, *p, *q, *r, *s, *quot, *new_r, *new_s, *temp; a = BN_new(); b = BN_new(); c = BN_new(); p = BN_new(); q = BN_new(); r = BN_new(); s = BN_new(); quot = BN_new(); new_r = BN_new(); new_s = BN_new(); temp = BN_new(); BN_copy(a,z); BN_copy(b,x); BN_one(p); BN_one(s); BN_zero(q); BN_zero(r); while (! BN_is_zero(b)) { BN_div(quot, c, a, b, BN_context); BN_copy(a,b); BN_copy(b,c); BN_mul(temp,quot,r,BN_context); BN_sub(new_r,p,temp); BN_mul(temp,quot,s,BN_context); BN_sub(new_s,q,temp); BN_copy(p,r); BN_copy(q,s); BN_copy(r,new_r); BN_copy(s,new_s); // printf("p %s, q %s, r %s, s %s\n", BN_bn2dec(p), BN_bn2dec(q),

BN_bn2dec(r), BN_bn2dec(s)); if (relprime) { BN_copy(target, a); else { if (q->neg) { BN_add(target,s,q); else { BN_copy(target,q); BN_free(a); BN_free(b); BN_free(c); BN_free(p); BN_free(q); BN_free(r); BN_free(s); BN_free(quot); BN_free(new_r); BN_free(new_s); BN_free(temp); // printf("target %s\n", BN_bn2dec(target)); genererer en 'bits' stor RSA-nà kkel privat nã kkel lagres i filen 'priv' offentlig nã kkel lagres i filen 'pub' void generatekey(unsigned int bits) { BIGNUM* p = BN_new(); BIGNUM* q = BN_new(); BIGNUM* n = BN_new(); BIGNUM* totient = BN_new(); BIGNUM* d = BN_new(); BIGNUM* e = BN_new(); BIGNUM* gcd = BN_new(); unsigned p_tests = 1; unsigned q_tests = 1; millerrabinbntemp bntemp; FILE* key; // pã de fleste *NIX-plattformer blir random-generatoren til // OpenSSL automatisk seeded if (! RAND_status()) { printf("error; random-generator has not been seeded\n"); exit(1); // STEG 1 // generer et tilfeldig oddetall if (! BN_rand(p, (bits / 2), 1, 1)) { printf("error generating rand p\n"); if (! BN_rand(q, (bits / 2), 1, 1)) { printf("error generating rand q\n"); millerrabinbninit(&bntemp); printf("generating p\n"); while (millerrabintestbn(p, 10, &bntemp)) { BN_add(p, p, two); p_tests++;

printf("generating q\n"); while (millerrabintestbn(q, 10, &bntemp)) { BN_add(q, q, two); q_tests++; millerrabinbnfree(&bntemp); printf("p tested %d times, q tested %d times\n", p_tests, q_tests); // STEG 2 BN_mul(n, p, q, BN_context); // STEG 3 BN_sub_word(p, 1UL); BN_sub_word(q, 1UL); BN_mul(totient, p, q, BN_context); // STEG 4 do { BN_set_word(e, 0); while (BN_is_one(e) BN_is_zero(e)) { BN_rand_range(e, totient); extgcdbn(gcd, totient, e, 1); while (! BN_is_one(gcd)); // STEG 5 extgcdbn(d, totient, e, 0); key = fopen("priv", "w"); BN_print_fp(key, n); fprintf(key, "\n"); BN_print_fp(key, d); fprintf(key, "\n"); fclose(key); key = fopen("pub", "w"); BN_print_fp(key, n); fprintf(key, "\n"); BN_print_fp(key, e); fprintf(key, "\n"); fclose(key); printf("remember TO PROTECT FILE 'priv'\n"); krypterer stdin, lagrer til cipher.txt bruker offentlig nã kkel fra 'key' void RSAencrypt(FILE* key) { BIGNUM *n, *e, *plain, *cipher, *temp; size_t n_size, e_size; char *nstr, *estr; unsigned char *plaintext; unsigned int textpos = 0; unsigned int bitsize = 0; FILE* ciphertext; n_size = 1; while (fgetc(key)!= 0x0a) n_size++; e_size = 1; while (fgetc(key)!= 0x0a)

e_size++; if (n_size < e_size) { printf("error; n_size < e_size\n"); exit(1); bitsize = n_size - 1; nstr = malloc(n_size); estr = malloc(e_size); rewind(key); fread(nstr, n_size, 1, key); fread(estr, e_size, 1, key); nstr[bitsize] = 0x0; estr[bitsize] = 0x0; n = BN_new(); e = BN_new(); plain = BN_new(); cipher = BN_new(); temp = BN_new(); BN_hex2bn(&n, nstr); BN_hex2bn(&e, estr); ciphertext = fopen("cipher.txt", "w"); plaintext = malloc(bitsize / 2); while (! feof(stdin)) { char current = getchar(); if (feof(stdin)) { plaintext[bitsize / 2] = 0x0; textpos = bitsize; // printf("end!\n"); else { plaintext[textpos] = current; textpos++; if (textpos >= (bitsize / 2)) { plaintext[bitsize / 2] = 0x0; BN_bin2bn(plaintext, bitsize / 2, plain); modexponentiationbn(cipher, plain, e, n, temp); // printf("%s => %s\n", BN_bn2hex(plain), BN_bn2hex(cipher)); fprintf(ciphertext, "%0*s", bitsize, BN_bn2hex(cipher)); textpos = 0; memset(plaintext, 0, bitsize / 2); fclose(ciphertext); dekrypterer stdin, lagrer til plain.txt bruker privat nã kkel fra 'key' void RSAdecrypt(FILE* key) { BIGNUM *n, *d, *plain, *cipher, *temp; size_t n_size, d_size; char *nstr, *dstr;

char *ciphertext; unsigned char *plaintext; unsigned int textpos = 0; unsigned int bitsize = 0; FILE* plaintext; n_size = 1; while (fgetc(key)!= 0x0a) n_size++; d_size = 1; while (fgetc(key)!= 0x0a) d_size++; if (n_size < d_size) { printf("error; n_size < d_size\n"); exit(1); bitsize = n_size - 1; nstr = malloc(n_size); dstr = malloc(d_size); rewind(key); fread(nstr, n_size, 1, key); fread(dstr, d_size, 1, key); nstr[bitsize] = 0x0; dstr[bitsize] = 0x0; n = BN_new(); d = BN_new(); plain = BN_new(); cipher = BN_new(); temp = BN_new(); BN_hex2bn(&n, nstr); BN_hex2bn(&d, dstr); plaintext = fopen("plain.txt", "w"); ciphertext = malloc(bitsize); plaintext = malloc(bitsize); while (! feof(stdin)) { char current = getchar(); ciphertext[textpos] = current; textpos++; if (textpos >= (bitsize)) { ciphertext[bitsize] = 0x0; BN_hex2bn(&cipher, ciphertext); modexponentiationbn(plain, cipher, d, n, temp); // printf("%s => %s\n", BN_bn2hex(cipher), BN_bn2hex(plain)); BN_bn2bin(plain, plaintext); fprintf(plaintext, "%.*s", bitsize, plaintext); textpos = 0; fclose(plaintext);

int main (int argc, const char * argv[]) { FILE* key; dir\n" dir\n"); one = BN_new(); two = BN_new(); BN_context = BN_CTX_new(); BN_set_word(one, 1UL); BN_set_word(two, 2UL); if (argc <= 1) { printf("usage: \n" "\t'genkey (bits)': Generate Private/Public\n" "\t'encrypt': encrypts stdin using key in current "\t'decrypt': decrypts stdin using key in current if (! strcmp(argv[1], "genkey")) { unsigned int bits; if (argc <= 2) { printf("missing keylength\n"); bits = strtol(argv[2], NULL, 10); printf("generating %d bits key\n", bits); // TODO: sjekk stã rrelsen av nã kkel generatekey(bits); return 0; if (! strcmp(argv[1], "encrypt")) { if (argc <= 2) { printf("specify which private keyfile to use\n"); key = fopen(argv[2], "r"); if (! key) { printf("failed to open keyfile\n"); RSAencrypt(key); fclose(key); return 0; if (! strcmp(argv[1], "decrypt")) { if (argc <= 2) { printf("specify which private keyfile to use\n"); key = fopen(argv[2], "r"); if (! key) { printf("failed to open keyfile\n"); RSAdecrypt(key); fclose(key); return 0;

return 0;