Obligatorisk Oppgave 1. INF Sikkerhet i distribuerte systemer

Like dokumenter
INF 1010, vår 2005 Løsningsforslag uke 11

Kryptografi og nettverkssikkerhet

Hva er verdien til variabelen j etter at følgende kode er utført? int i, j; i = 5; j = 10; while ( i < j ) { i = i + 2; j = j - 1; }

INF Løsning på seminaropppgaver til uke 8

UNIVERSITETET I OSLO

Kryptografi og nettverkssikkerhet

Tor-Eirik Bakke Lunde

INF1000 (Uke 15) Eksamen V 04

INF1000 (Uke 15) Eksamen V 04

TOD063 Datastrukturer og algoritmer

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

INF1000 Prøveeksamen Oppgave 7 og 9

Obligatorisk oppgave 1 i INF 4130, høsten 2009

Kom forberedt til tirsdag. INF1000 Tips til obligatorisk oppgave 4. Noen generelle tips. Oblig4: Komme igang

IN1010 våren januar. Objektorientering i Java

Kapittel 9: Sortering og søking Kort versjon

Kapittel 8: Programutvikling

UNIVERSITETET I OSLO

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

INF1010 våren 2019 Onsdag 30. januar. Mer om unntak i Java (med litt repetisjon av I/O først)

UNIVERSITETET I OSLO

Eksamen i emnet INF100 Grunnkurs i programmering (Programmering I) Løsningsforslag

Tor-Eirik Bakke Lunde

Læreboken på 45 minutter

UNIVERSITETET I OSLO

INF1010 våren 2018 tirsdag 23. januar

Obligatorisk oppgave 1 i INF 4130, høsten 2008

Introduksjon til objektorientert programmering

programeksempel Et større En større problemstilling Plan for forelesingen Problemstillingen (en tekstfil) inneholdt ordet "TGA"

Tor-Eirik Bakke Lunde

Forkurs INF1010. Dag 1. Andreas Færøvig Olsen Tuva Kristine Thoresen

Innhold uke 4. INF 1000 høsten 2011 Uke 4: 13. september. Deklarasjon av peker og opprettelse av arrayobjektet. Representasjon av array i Java

UNIVERSITETET I OSLO

INF1010 våren januar. Objektorientering i Java

Løsningsforslag, inf101, våren 2001

Løsningsforslag for Obligatorisk Oppgave 3. Algoritmer og Datastrukturer ITF20006

Konstruktører. Bruk av konstruktører når vi opererer med "enkle" klasser er ganske ukomplisert. Når vi skriver. skjer følgende:

Forelesning inf Java 5

INF1010 Sortering. Marit Nybakken 1. mars 2004

Forelesning inf Java 5

OPPGAVE 1 OBLIGATORISKE OPPGAVER (OBLIG 1) (1) Uten å selv implementere og kjøre koden under, hva skriver koden ut til konsollen?

"behrozm" Oppsummering - programskisse for traversering av en graf (dybde først) Forelesning i INF februar 2009

"Nelsons kaffebutikk"

UNIVERSITETET I OSLO

INF1000: Forelesning 4. Mer om arrayer Metoder

INF1000 EKSTRATILBUD. Stoff fra uke 1-5 (6) 3. oktober 2012 Siri Moe Jensen

Videregående programmering 6

UNIVERSITETET I OSLO

Kapittel 8: Sortering og søking INF100

INF1010 våren 2017 Onsdag 25. januar. Litt om unntak i Java

HØGSKOLEN I SØR-TRØNDELAG

UNIVERSITETET I OSLO

INF Uke 10. Ukesoppgaver oktober 2012

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

Klasser, objekter, pekere og UML. INF gruppe 13

I et Java-program må programmøren lage og starte hver tråd som programmet bruker. Er dette korrekt? Velg ett alternativ

IN1010. Fra Python til Java. En introduksjon til programmeringsspråkenes verden Dag Langmyhr

Array&ArrayList Lagring Liste Klasseparametre Arrayliste Testing Lenkelister

Fra Python til Java. En introduksjon til programmeringsspråkenes verden. Dag Langmyhr

INF2100. Oppgaver 23. og 24. september 2010

INF Notat om I/O i Java

Løse reelle problemer

1- og 2-veis Innkapsling Java Stabel Kø Prio-kø Iterator. Enveis- og toveislister Innkapsling («boxing») (Big Java 6.8.5)

INF Seminaroppgaver til uke 3

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

Løsningsforslag for Obligatorisk Oppgave 2. Algoritmer og Datastrukturer ITF20006

Løsningsforslag ukeoppg. 6: 28. sep - 4. okt (INF Høst 2011)

INF1000 oppgaver til uke 38 (17 sep 23 sep)

Litt om Javas class-filer og byte-kode

Avdeling for ingeniørutdanning Institutt for teknologi

NOTAT (pensum!) Javas klasse-filer, byte-kode og utførelse

UNIVERSITETET I OSLO Det matematisk-naturvitenskapelige fakultet

IN1010. Fra Python til Java. En introduksjon til programmeringsspråkenes verden Dag Langmyhr

Kapittel 8: Sortering og søking INF100

Forelesning inf Java 4

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

i=0 Repetisjon: arrayer Forelesning inf Java 4 Repetisjon: nesting av løkker Repetisjon: nesting av løkker 0*0 0*2 0*3 0*1 0*4

NOTAT (pensum!) Javas klasse-filer, byte-kode og utførelse. INF 5110, 10/5-2011, Stein Krogdahl

En algoritme for permutasjonsgenerering

INF1000: noen avsluttende ord

UNIVERSITETET I OSLO

IN Notat om I/O i Java

Gjennomgang av eksamen H99

INF1010, 15. januar time. Parametriserte klasser (generiske klasser) Stein Gjessing Inst. for Informatikk Universitetet i Oslo

Innlevering 2b i INF2810, vår 2017

Kapittel 9: Sortering og søking Kort versjon

Løsnings forslag i java In115, Våren 1998

Kryptering med vigenere-metoden

2 Om statiske variable/konstanter og statiske metoder.

Obligatorisk oppgave 1 INF1020 h2005

TDT4100 Objektorientert programmering

Algoritmer og datastrukturer Kapittel 3 - Delkapittel 3.1

Oblig 4 (av 4) INF1000, høsten 2012 Værdata, leveres innen 9. nov. kl

MER OM ARRAYER. INF1000: Forelesning 4. Anta at vi ønsker å lagre en liste med navnene på alle INF1000-studentene:

Forklaring til programmet AbstraktKontoTest.java med tilhørende filer Konto.java, KredittKonto.java, SpareKonto.java

Mål med kurset. Java i INF Dagens tema. GUI med Swing. Dokumentasjon

UNIVERSITETET I OSLO

Eks 1: Binærtre Binærtretraversering Eks 2: Binærtre og stakk

Transkript:

Obligatorisk Oppgave 1 INF-2310 - Sikkerhet i distribuerte systemer 1

Innholdsfortegnelse: Forside s. 01 Innholdsfortegnelse s. 02 Del I Selvtest s. 03 Del II CBC/PKCS#5 s. 05 Generalisert PKCS#5 Implementasjon s. 08 Cipher Block Chaining (CBC) Implementasjon s. 09 Selvtest Teste implementasjonen s. 10 Del III Testing: JCE vs. Selvlaget s. 11 Appendix A Filoversikt s. 11 2

Del I - Selvtest: Kryptere en klartekst, dekryptere den resulterende kryptoteksten, og så å sjekke at resultatet av dekrypteringen er identisk med klarteksten i utgangspunktet. Implementasjonen av del 1, er vedlagt med filnavn xxcrypt.java og viser i praksis det som blir gjennomgått i denne delen av oppgaven. import javax.crypto.cipher; import java.security.key; import javax.crypto.spec.secretkeyspec; public class xxcrypt { public static void main(string[] args) throws Exception { // Henter ut gyldig IvParameterSpec for bruk til kryptering/dekryptering. byte[] initvector = { 0, 0, 0, 0, 0, 0, 0, 0 ; IvParameterSpec iv = new IvParameterSpec(initVector); // Konverterer nøkkelstrengen til noe vi kan bruke, dvs ett bytearray. byte[] keyb = Hex.fromString( fedcba9876543210123456789abcdeff ); // Bruker denne til å lage en nøkkel til algoritmen i form av ett SecretKeySpec // objekt. Key key = new SecretKeySpec(keyB, IDEA/CBC/PKCS#5 ); // Henter ut en instans av Cipher som implementerer ønsket algoritme. Cipher _cp = Cipher.getInstance( IDEA/CBC/PKCS#5 ); // Cipher klargjøres for bruk og settes til krypteringsmodus _cp.init(cipher.encrypt_mode, key, iv); // Krypterer teksten og skriver den til skjermen byte[] encryptt = _cp.dofinal(message.getbytes( ISO8859_1 )); System.out.println( Encrypted text: + Hex.toString(encryptT)); // Klargjør Cipher på nytt men nå for å dekryptere tekst. _cp.init(cipher.decrypt_mode, key, iv); byte[] decryptt = _cp.dofinal(encryptt); System.out.println( Decrypted text: + new String(decryptT, ISO8859_1 )); 3

Det overdokumenterte utdraget ovenfor viser ikke i sin helhet den store mengden funksjonalitet som støttes via Java Cryptographic Environment (JCE). Ved kjøring av dette eksemplet vil en kunne se at teksten blir kryptert og så dekryptert for å muliggjøre sammenligning mellom den originale og den teksten en satt igjen med til slutt. Den vedlagte filen til denne delen overlater valget av initialiseringsvektor til JCE og blir dermed generert tilfeldig av denne og da er unødvendig for denne implementasjonen dette forutsetter da at kryptering og dekryptering foretas av samme objekt eller Iv-informasjon utveksles. En eksempelvis kjøring av dette programmet ga følgende output: Encrypted text: 031C0D9D98EE389B0A60C62163D34DA2E48FF4AA442A341BA783DBB9AD58EB0B Decrypted text: it loves my foo, does it not? Decrypted text matches original text... True 4

Del II CBC/PKCS#5: Implementere Cipher Block Chaining (CBC) modus og PKCS#5 padding uten bruk av JCE. En egnet implementasjon av IDEA vil bli brukt til selve kryptering / dekrypteringen. I lys av del 3 av oppgaven og for letthets skyld har jeg valgt å legge til ett ekstra lag av abstraksjon mellom programmene som benytter JCE eller vår egen implementasjon og dermed gi dem ett felles uniformt programmerings API, som dermed også som antydet angående fremtidige obligatoriske innleveringer kan være til stor hjelp. Også dermed ved å stadfeste hvilke funksjoner som skal være støttet vil det være lettere å implementere egnede implementasjoner av disse. Dette resulterte i en abstrakt klasse kalt CryptoEngine, med funksjoner og konstanter i henhold til UML diagrammet på neste side. Hver implementasjon av denne klassen må også da implementere de abstrakte funksjonene som er definert i denne sammenhengen: public abstract class CryptoEngine { abstract public byte[] encrypt(byte[] data) throws Exception; abstract public byte[] decrypt(byte[] data) throws Exception; For enkelhet er ikke unntakshåndtering gjennomført på noe revolusjonerende nivå i oppgave og blir bare kastet videre til den uheldige brukeren av systemet. Likevel etter å ha definert disse er det da en smal sak å lage en implementasjon som bruker JCE og en implementasjon laget av oss selv samt enda lettere å få dem til å samarbeide. For å lette bruken har jeg i likhet med JCE laget en getinstance funksjon som tar ett nummer som argument og returnerer en instans av den ønskede implementasjon. Dette muliggjør følgende kode: CryptoEngine ce = CryptoEngine.getInstance(CryptoEngine.JCE_Implementation, KEY, IV); // eller denne for å bruke egen implementasjon CryptoEngine ce = CryptoEngine.getInstance(CryptoEngine.Own_Implementation, KEY, IV); 5

Nå da formalitetene med det overliggende abstraksjonslaget er tilbakelagt kan en konsentrere seg om de hovedsaklige implementasjonsmessige detaljene over vår egen implementasjon av CBC og PKCS#5. UML diagram over min egen implementasjon av dette er vist her til venstre. En detaljert gjennomgang av hver funksjon er overflødig ettersom denne informasjonen er tilgjengelig i medfølgende dokumentasjon. For å lette implementasjonen av CBC er det innført en ny klasse i tillegg til denne som representerer en enkelt blokk data med andre ord en slags wrapperklasse for ett 8 byte array. 6

Generalisert PKCS#5 Implementasjon: Når en skal implementere en Cipher kan en ikke stole på at den teksten som skal krypteres passer fint inn i et visst antall ( hele ) blokker, og da vil det være nødvendig å bruke en form for padding. IDEA algoritmen krever en blokkstørrelse på 64 bit (8 byte) for å fungere, og det er her generalisert PKCS#5 padding kommer inn for å fylle ut resten av blokk. Det vil si at klarteksten M og en paddingsekvens S settes sammen til paddingsekvensen M. S består av n ( M mod n) oktetter med verdien n ( M mod n), hvor n er cipherens blokkstørrelse i oktetter. Eksempelvis kan vi forestille oss at vi deler den dataen som skal krypteres inn i 8 byte blokker, og i den siste blokken ender vi opp med kun 5 byte da. Ettersom IDEA krever at hver blokk skal være på 8 byte har vi ett 3 byte tomrom som må paddes ut. I henhold til PKCS#5 padder vi da ut disse bytene med verdien 3 (0x03 i hex). For å bedre vise hvordan dette gjøres, observer følgende eksempler (hvorav Data angir sekvenser av 8 bit data): I det siste eksemplet ser vi hva som skjer dersom all dataen tilfeldigvis fyller ut alle blokkene. Det en da gjør for å sikre at denne kodingen gir en utvetydig gjenoppretting av M fra M er at det legges til en ekstra blokk paddet helt ut. Følgene for dette er at vi nå med sikkerhet vet at den siste blokken alltid inneholder padding når denne da etter hvert skal fjernes igjen. I min implementasjon av PKCS#5 har jeg lagt inn en ekstra test på dataen som sjekker at en ikke prøver å fjerne padding fra data som ikke er paddet det vil si at siste byte i siste blokk må ha en gyldig verdi (mellom 0x01 og 0x08) i tillegg til at de bytene som er paddet må være paddet med samme verdi. Dersom disse forutsetningene ikke sammenfalles kastes en Exception med beskjeden Invalid padding detected. Fornevnte implementasjon er å finne i klassen OwnImplement og funksjonene getpaddedblocks( ) og removepadding( ). getpaddedblocks(...): Tar ett array av bytes som argument. Disse bytene konverteres til en serie datablokker og paddes ut i henhold til PKCS#5. Resultatet returneres i form av ett array datablokker. Det første som skjer er at antall tomrom som blir i den siste blokken kalkuleres. Det neste som skjer er at dersom det ikke ble noen tomrom legges det til en blokk paddet ut med 0x08 som vist i nederste eksempel i diagrammet ovenfor. Hvis dette ikke var tilfelle blir den siste blokken paddet ut. Når da dette er gjennomført returneres resultatet og det hele er klart til kryptering. 7

Implementasjon av PCKS#5: public DataBlock[] getpaddedblocks(byte[] data) { int leftover = data.length - ((data.length / 8) * 8); int blocks = (data.length / 8) + 1; DataBlock[] db; byte[] pad = {8, 8, 8, 8, 8, 8, 8, 8; if (leftover == 0) { db = new DataBlock[blocks]; for (int i = 0; i < (blocks - 1); i++) db[i] = new DataBlock(data, (i * 8)); db[blocks - 1] = new DataBlock(pad); else { db = new DataBlock[blocks]; for (int i = 0; i < (blocks - 1); i++) db[i] = new DataBlock(data, (i * 8)); for (int i = 0; i < leftover; i++) pad[i] = data[((blocks - 1) * 8) + i]; for (int i = 0; i < (8 - leftover); i++) pad[i + leftover] = (byte)(8 - leftover); db[blocks - 1] = new DataBlock(pad); return db; removepadding(...): Tar ett array av datablokker som argument. Den siste byten i den siste datablokken indikerer hvor mange bytes som skal fjernes. Hvis antallet bytes er 8, det vil si en hel blokk, fjernes denne blokken og resten av blokkene returneres. Deimplementasjon av PCKS#5: public DataBlock[] removepadding(datablock[] blocks) throws Exception { int remove = (int) blocks[blocks.length - 1].d[7]; if (remove == 8) { // Verifying that the datablock is sane for (int i = 0; i < 8; i++) if (blocks[blocks.length - 1].d[i]!= 8) throw new Exception( Invalid padding detected ); DataBlock[] temp = new DataBlock[blocks.length - 1]; for (int i = 0; i < (blocks.length - 1); i++) temp[i] = blocks[i]; return temp; else { // Verifying that the datablock is sane for (int i = 0; i < remove; i++) if (blocks[blocks.length - 1].d[7 - i]!= remove) throw new Exception( Invalid padding detected ); byte[] temp = new byte[8 - remove]; for (int i = 0; i < (8 - remove); i++) temp[i] = blocks[blocks.length - 1].d[i]; blocks[blocks.length - 1].d = temp; return blocks; 8

Cipher Block Chaining (CBC) Implementasjon: Ved kryptering av samme tekst flere ganger vil krypteringsalgoritmen alltid gi samme ciphertekst, og det er her Cipher moduser kommer inn. Den modusen vi benytter heter Cipher Block Chaining (heretter CBC). Kort sagt: Utfører en eksklusiv-eller operasjon på neste blokk klartekst med forrige genererte blokk ciphertekst. I første ledd benyttes i stedet initialiseringsvektor (IV) som forgående blokk. Den direkte implementasjonen av CBC er implementert i klassen OwnImplement i funksjonen encrypt( ). Funksjoner deler dataen som skal krypteres opp i en serie datablokker, rett og slett for å gi en mer ryddig implementasjon, som brukes under krypteringen. Se kode under for flere detaljer. encrypt( ): public byte[] encrypt(byte[] data) throws Exception { idea.initencrypt(key); DataBlock[] blocks = getpaddedblocks(data); DataBlock[] cipher = new DataBlock[blocks.length]; byte[] temp; for (int i = 0; i < blocks.length; i++) { if (i == 0) temp = xor(initvector, blocks[i].d); else temp = xor(cipher[i - 1].d, blocks[i].d); idea.blockencrypt(temp, 0, temp, 0); cipher[i] = new DataBlock(temp); return getbytes(cipher); Dekryptering foregår like enkelt fordi alle eksklusiv-eller operasjoner er sin egen invers, noe som vil si at prosessen mer eller mindre i reverseres. Se skisse og utdrag fra kildekoden under. 9

encrypt( ): public byte[] decrypt(byte[] data) throws Exception { idea.initdecrypt(key); DataBlock[] blocks = getblocks(data); DataBlock[] plain = new DataBlock[blocks.length]; byte[] temp = new byte[8]; for (int i = 0; i < (blocks.length); i++) { idea.blockencrypt(blocks[blocks.length - 1 - i].d, 0, temp, 0); if (i == (blocks.length - 1)) plain[blocks.length-1-i] = new DataBlock(xOr(initVector, temp)); else plain[blocks.length - 1 - i] = new DataBlock(xOr(blocks[blocks.length - 1 - i - 1].d, temp)); plain = removepadding(plain); return getbytes(plain); Selvtest Teste implementasjonen: Nå da både PKCS#5-padding og CBC var implementert gjenstår det bare og teste implementasjonen på de medfølgende ciphertekstene. Kildekoden til dette testprogrammet er vedlagt med filnavn Selvtest.java. En testgjennomkjøring gir følgende output: 1. Kokkos!! 2. Cogito Ergo Sum! 3. Dihydrogenmonoksid er et hvitt pulver. 4. 3.141592653589793238... 10

Del III Testing: JCE vs. Selvlaget: Nå som begge implementasjonene av CryptoEngine klassen i form av klassene JCEImplement og OwnImplement er ferdig implementert er testingen kun en liten gjenstående formalitet. Har implementert denne testen i egen fil kalt Testing.java. Appendix A Filoversikt: CryptoEngine.java: Hovedimplementasjonen av oppgaven og inneholder alle omtalte klasser og programstrukturer. Selvtest.java: Selvtest fra del II av oppgaven. Dekrypterer ciphertekstene oppgitt i oppgaven. Testing.java: Testen fra del III av oppgaven. Viser at begge implementasjonene kan snakke sammen. Bruker først min egen implementasjon til å kryptere en tekst og så JCE til å dekryptere den resulterende cipherteksten. Til sist blir det gjennomført en test om at den originale teksten og den dekrypterte teksten er 100% lik. Samme test blir også gjennomført der JCE krypterer og egen implementasjon dekrypterer. xxcrypt.java: Testfil fra del I av oppgaven. Viser bruk av JCE helt enkelt uten bruk av de mer avanserte strukturene fra filen CryptoEngine. 11