Kode implementasjoner er ikke med her, for det finnes det nok av på nettet allerede. Istedenfor skal vi forklare begrep og typer for de som har lyst til å ha en overordnet forståelse av hva krypto er og hvordan det fungerer. Vi hopper også glatt over all matte, men for de som er interesserte i dypdykk så listes det opp anbefalt litteratur på bunnen (langt ifra en komplett liste).
Hva er det krypto løser for oss?
Internett er en sone man kaller “untrusted”. Det betyr at alle noder og nett ansees som kompromitterte. Kryptografi gjør det mulig for oss å kommunisere trygt i et utrygt miljø. Hvis man bruker riktige metoder da, vel og merke. For selv om matematikken bak er viden kjent og vel testet, så er det et hav av fallgroper å gå i når man skal implementere kryptografiske løsninger. Ettersom datamaskiner blir raskere og raskere må også bit-størrelsen på nøklene bli større og større.
Kryptografi er det som gjør at vi kan kommunisere trygt med nettbanken, handle på nettbutikker med kort eller elektroniske betalingsmåter eller chatte med venner uten at en snusende tredjepart plukker opp alt vi sier.
Kryptografi er rett og slett nøkkelen til hvorfor vi i det hele tatt kan bruke internett, telefoner og de mange duppedittene vi nå installerer i hus og hytter. Dette betyr ikke at alt er trygt og godt. Langt ifra. Det er nemlig gode penger å tjene for en rekke firmaer på at ting ikke er kryptert. Så ting kan bli mye bedre. De som leverer krypterte systemer med gode intensjoner sliter også til tider, når det viser seg at de har implementert algoritmene feil, bruker feil modus, ikke håndterer nøkler riktig, bruker utdaterte metoder osv.
Krav til gode kryptoløsninger
Vår alles drøm er å ha perfekt kryptografi. Et system som det rett og slett er umulig å knekke. Dette kalles Perfect-Secrecy og den gode nyheten er at Claude Shannon la frem hvordan vi kan oppnå dette allerede på 40-tallet. Dette kalles One-Time-Pad (OTP). OTP garanterer perfekt hemmelighold. Det eneste som en angriper kan lære om ciphertexten er lengden. Den dårlige nyheten er at det har svært få bruksområder grunnet at praktikaliteter. I OTP må nemlig nøkkelen være like lang som dataen som krypteres. Ergo; 100 GB data krever en 100 GB nøkkel. Så vi må ta til takke med andre metoder for å oppnå sikker kommunikasjon.
Men før vi hopper inn i de forskjellige metodene se på noen konkrete krav til våre kryptografiske løsninger:
- Konfidensialitet: Dataene må være beskyttet slik at bare de som skal se dataene får tilgang
- Integritet: Det må garanteres at dataene som er sendt ikke er manipulert
- Autentisering: Mottaker må kunne verifisere at sender og data autentisk
- Non-Repudiation: Sender kan ikke nekte for å ha lagd meldingen
For å imøtekomme disse kravene benyttes en kombinasjon av symmetrisk og asymmetrisk kryptografi, hashing og Message Authentication Codes (MAC). Vi skal straks ta en kikk på alt dette, men først må vi definere noen begrep:
- Plaintext: Dette er informasjonen vi ønsker å holde hemmelig
- Ciphertext: Dette er informasjonen etter den er kryptert.
- Nøkkel: Dette er nøkkelen til å kryptere eller dekryptere
- Algoritmen: Dette er selve krypteringsimplementasjonen
Vi trenger også en oversikt over hvordan en angriper kan gjøre hverdagen vår sur, og hvorfor «tilfeldige» tall er så viktig i all krypto.
Guide: Slik utfører du sikkerhetstesting gjennom utviklingsløpet
Vil du lære mer om sikkerhet og sikkerhetstesting? I denne guiden gjennomgår sikkerhetsekspert Even Lysen hvordan du kan utføre sikkerhetstesting gjennom hele utviklingsløpet.
Angrep mot kryptoløsninger
Det er en rekke angrep som trusselaktører kan utføre mot krypteringsløsninger, og dette kan deles inn i to kategorier: Passive og Aktive. Passive angrep er der hvor trusselagenten utfører angrep på selve ciphertexten, mens i aktive angrep så brukes også implementasjonen. En angriper vil alltid forsøke å få hold på nøkkelen.
Passive kryptoløsninger
- Ciphertext-Only. Dette er direkte forsøk på å knekke den krypterte biten (ciphertext). Angriper har ikke tilgang til hverken plaintext eller den implementerte algoritmen. Angriper kan ikke utføre kryptering eller dekryptering av egen plaintext.
- Known–Plaintext. Her har angriper tilgang på plaintext-ciphertext par. Angriper har ikke tilgang på krypteringsimplementasjonen og kan ikke kryptere sine egne plaintexts.
Aktive kryptoløsninger
- Chosen-Plaintext. Angriper kan kryptere egne plaintexts og motta tilhørende ciphertext. Angriper har ikke nødvendigvis tilgang til andre tilfeldige bits som legges på plaintext som en del av krypteringen.
- Chosen-Ciphertext. Her har angriper mulighet til å kryptere og dekryptere valgt plaintext og ciphertext. Det en angriper er ute etter her er å finne nøkkelen som benyttes. Dette gjelder spesielt for hardware enheter.
- Side-Channel Attacks. En type angrep som går ut på å observere hvordan krypteringen foregår. F.eks. se på hvor lang tid ting tar, feilmeldinger, verdier som endrer seg på systemet rundt, strømbruk, etc.
- Invasive Attacks. Betegner dyre angrep som oftest er rettet mot hardware kryptering og krever spesialister og spesialistutstyr.
Tilfeldige tall
Kerchoff’s prinsipp sier at «sikkerheten i et kryptosystem må alene ligge på valget av nøkkel, mens alt annet bør anses som offentlig tilgjengelig». Dette betyr at sikkerheten til dagens kryptosystemer ligger i hvor vanskelig det er for en angriper å finne nøkkelen.
En nøkkel er tilfeldige bits. Det å generere en serie med tilfeldige bits er uhyre vanskelig, og krever egentlig en analog input. I en vanlig konsument datamaskin kan det være hardware moduler spesielt laget for å generere tilfeldige sekvenser. Et eksempel er intel sine CPU f.o.m. Ivy Bridge modellen. I software har vi ikke mulighet til å generere ekte tilfeldige serier så her må man nøye oss med pseudotilfeldige tall. For å generere tilfeldige tall trenger man en kilde som kan produsere nettopp dette. Kilden til tilfeldighet (kalt Entropi) i software vil være musebevegelser, CPU temperatur, RAM layout, harddisk aktivitet, nettverkstrafikk, etc. De pseudotilfeldige verdiene lagres i en entropi pool på OS nivå som deretter er seed verdien i den pseudotilfeldige tall generatoren (kalt PRNG).
De fleste moderne programmeringsspråk har klasser spesielt for pseudotilfeldige tall, men de er sjelden klassen som heter Rand eller Random. I C# på Windows kan man benytte klassen RNGCryptoServiceProvider. På Linux kan benytte /dev/urandom.
Hashing
Hashing er ikke kryptering, selv om mange snakker som om det skulle være det. Når du krypterer så er tanken at du skal gjøre plaintext hemmelig, men med mulighet til å dekryptere den tilbake til leselig format. Hashing derimot er når du tar en plaintext og kjører den gjennom en hashing algoritme som f.eks. SHA512 så får du ut en kryptografisk hash verdi som ikke kan reverseres. Hashing er en enveis operasjon.
Hashing har flere bruksområder. De to mest kjente er for å lagre passord på en trygg måte, og den andre er for integritetssjekker. Følgende regler for hash funksjoner:
- To forskjellige plaintext skal ikke kunne bli til samme hash kode.
- Enhver endring i plaintext skal gi en totalt annerledes hash kode.
- Du skal ikke kunne lage en plaintext som gir deg en spesiell hash kode.
Den mest kjente hashing metoden er MD5, som fortsatt er i vid bruk. Selv om MD5 er knekt for lenge siden. Problemet med MD5 er at den lider av et Collision-Attack som betyr at det er mulig å få to forskjellige typer plaintext til å ende opp med samme hash kode.
De som ansees som trygge i dag er underlagt SHA-2 familien. De kalles SHA256 og SHA512. 256 og 512 refererer til bit-størrelsen. Det finnes mange forskjellige hashing algoritmer og de er alle ment til hvert sitt bruk. For eksempel skal man ikke bruke SHA1/2/3 familie algoritmer for passord hashing (selv med salt). For passord hashing anbefales det at man benytter PBKDF2 eller bcrypt. Scrypt er arvtager til bcrypt, men grunnet kort fartstid er den p.t. ikke anbefalt (men på sikt vil den nok ta over). Det finnes også kjente angrepsvektorer på PBKDF2 og bcrypt, men disse er brute-force angrep og regnes som usannsynlige hvis lengden på passordet er over 10 karakterer.
Et ord nevnt ovenfor er SALT. Salt brukes oftest i forbindelse med hashing av passord. Salt er en streng med tekst som settes foran brukerens passord før de sammen forsvinner inn i hashing algoritmen. Dette er for å gjøre brute-force angrep mye vanskeligere, men også for at to like passord ikke skal bli den samme hashen. Hvis salt verdien er av god størrelse så gjør dette at brute-force angrep fort blir for tidkrevende.
Symmetrisk Kryptering
Symmetrisk kryptering betyr at man benytter samme nøkkel til både kryptering og dekryptering. Standardalgoritmen her kalles AES (Advanced Encryption Standard) og kommer i forskjellige bit-versjoner (forskjellige bit-størrelse på nøkkelen. Bit-størrelsen på blokkene er 128 på alle tre). Det var mange kandidater til hva som skulle bli arvtageren til 3DES (Data Encryption Standard), og det var Rijndael som ble kåret til vinner. De forskjellige versjonene er AES128, AES192 og AES256.
Symmetrisk kryptografi kommer i to hovedgrupper:
- Block cipher: Her deles bitsene som skal krypteres inn i like blokkstørrelser (64 bits eller mer). Deretter kjøres en algoritme som krypterer hver blokk med krypteringsnøkkelen. Block ciphers må lagre data i minnet før det krypteres ettersom selve krypteringsjobben ikke starter før man har nok bits til å fylle en blokk. Dette kan være et potensielt sikkerhetshull, og et tiltak mot dette er at blokkene minimeres og blandes med forrige krypterte blokk frem til nok bits for neste blokk er på plass.
- Stream cipher: Stream ciphers krypterer en byte om gangen og er betydelig raskere enn Block cipher algoritmer. En annen forskjell er at Stream Ciphers ikke trenger å lagre data i minnet før det blir kryptert.
De to forskjellige metodene å implementere symmetrisk kryptografi på kan også kjøres i forskjellige typer modus. Modus er hvordan selve krypteringen skal foregå på blokkene eller på streams. De vanligste modusene er:
- ECB (Electronic Code Book): Den enkleste modusen er ECB og den er betraktet som høyst utrygg. Her benyttes samme nøkkel til å kryptere hver eneste blokk. Den kan kryptere flere blokker i parallell, men det er en direkte relasjon mellom plaintext og ciphertext. Den mest kjente måten å demonstrere ECB sin svakhet på er å kryptere et bitmap bilde. Da vil man fortsatt se det samme bilde, men med andre farger. Krever også at siste blokken blir paddet.
- CBC (Cipher Block Chaining): En forbedret versjon av ECB. Her krypteres hver blokk med nøkkel og ciphertexten til forrige krypterte blokk. Dette betyr at prosessen ikke kan kjøre i parallell, og at enhver feil som skjer vil gi følgefeil på resten av prosessen). Padding av siste blokk er nødvendig.
- CFB (Cipher Feedbacck Mode): Lik CBC men er selv-synkroniserende. Ergo, en feil produsert på en blokk vil ikke gi feil på de neste. Krever heller ikke at blokkene er paddet som gjør at plaintext og ciphertext blir like lange.
- OFB (Output Feedback Mode): Gjør et block cipher til et stream cipher. Kombinerer nøkkeelen med en IV (Initialization Vector) som genererer keystream blokker som kjører en XOR med plaintext. Krever heller ikke padding og plaintext er like lang som ciphertext.
- CTR (Counter Mode): Veldig lik OFB men istedenfor en keystream basert på nøkkel og IV benyttes en teller. Får ikke følgefeil og egner seg godt til parallellisering.
- Padding: Padding er å legge til bits for å fylle opp den siste blokken som skal krypteres. Det finnes mange forskjellige padding metoder, men de mest populære er PKCS#5, PKCS#7 og ANSI X9.23.
- IV (Initialization Vector): Den første blokken som krypteres kan ikke kombineres med andre blokker ettersom det er den første. For å øke tilfeldigheten i blokken benyttes en IV som er et sett med tilfeldige bits. Det viktige er at en IV bare benyttes en gang, men den er ikke ansett som sensitiv. IV må sendes sammen med krypteringsnøkkel til den som skal dekryptere dataene. En IV er å ansees som en nonce.
- Nonce: Står for: Number Used Once. Generelt begrep om en verdi som sendes inn i en kryptoalgoritme eller hashing algoritme som bare skal brukes en gang.
Det finnes mange flere moduser en kryptoalgoritme kan kjøre i. Mange er utviklet til spesifikke bruksområder. Spørsmålet blir alltid hvilken type skal jeg bruke med hvilken modus?
Stream ciphers benyttes ikke så ofte i dag grunnet at det ble oppdaget flere svakheter rundt hvordan de fungerer (det finnes allikevel noen gode og de mest populære er Salsa20 og ChaCha20). Derfor er det vanligste at man benytter en block cipher med en modus som imiterer funksjonalitet til stream ciphers. For en grundig gjennomgang av fordelere og ulemper med Block cipher moduser anbefales det å lese «Evaluation of Some Blockcipher Modes of Operation» av Philip Rogaway fra 2011. Dette er 159 sider ren page-turner prosa (jeg tuller ikke). Det vanligste i dagens bruk er versjoner av CBC.
Symmetrisk kryptering benyttes til alt fra disk og filkryptering. Databaser, konfigurasjonsfiler, dokumenter, etc. Fordelen med symmetrisk kryptering er at det er veldig raskt og effektivt. Utfordringen er nøkkelhåndtering. Hvis det er flere som skal ha tilgang til de krypterte dataene så må man benytte samme nøkkel. Dette kalles en Shared Secret. Hvordan utveksler man denne nøkkelen på en trygg måte over en utrygg kanal? Det er det Asymmetrisk Kryptering hjelper oss med.
Det som er veldig viktig å huske på er at kryptering bare gir deg konfidensialitet. Det gir deg ikke integritet eller autentisering. Det sier heller ikke noe om når meldingen ble laget. Symmetrisk kryptografi skalerer også med tanke på nøkkeldistribusjon. For å imøtekomme slike behov trenger vi å kombinere symmetrisk kryptografi med asymmetrisk kryptografi, hashing metoder og tellere.
Asymmetrisk kryptering
Mer kjent som Public Key kryptografi. Her er det to nøkler som har en matematisk relasjon som benyttes. En Public (offentlig) nøkkel som krypterer data, og en Privat nøkkel som kan dekryptere data. Årsaken til at man krever høyere bits på asymmetrisk enn symmetrisk krypto er at nøklene benytter faktorisering av primtall. Det er dette som gjør det mulig å ha to relaterte nøkler, og sikkerheten ligger i at det er vanskelig å finne ut hvilke primtall som er benyttet for å generere nøklene. Samtidig gjør dette at keyspace er mindre med færre bits, ergo man trenger flere bits for å kunne dekke store tall og ha et keyspace stort nok til å stå i mot et angrep. Jo kraftigere datamaskiner blir jo raskere kan de beregne nøklene. Det er asymmetrisk krypto som står i fare hvis (når?) vi får fullverdige kvantedatamaskiner. Det har i mange år vært anbefalt å benytte 2048 bits versjoner, men 4096 blir mer og mer vanlig.
Asymmetrisk kryptering har et problem og det er hastighet. Å kryptere store mengder data er rett og slett for tidkrevende, så derfor benyttes symmetrisk krypto primært til slike jobber. Det asymmetrisk krypto derimot løser er å kunne utveksle nøkler trygt over utrygge kanaler.
Se for deg at Alice vil sende Bob en hemmelig beskjed, men de sitter på hver sin side av atlantern og må gjøre dette over internett som er en utrygg kanal.
- Alice lager et nøkkelsett (public og privat) og legger public key tilgjengelig for alle.
- Bob skriver sin hemmelige melding (plaintext).
- Bob krypterer plaintext meldingen med en symmetrisk nøkkel og en IV.
- Bob bruker Alice sin public nøkkel til å kryptere sin symmetriske nøkkel og IV og sender det sammen med den krypterte meldingen over til Alice.
- Alice mottar to krypterte pakker. En med kryptert melding og den andre med nøkkel og IV.
- Alice dekrypterer pakken med den symmetriske nøkkelen og IV med sin private nøkkel.
- Alice dekrypterer meldingen med den mottatte symmetriske nøkkelen og IV.
Dette løser hvordan man kan distribuere den symmetriske nøkkelen trygt over en utrygg kanal, men Alice trenger fortsatt å verifisere integriteten i sendingen og autentisere avsender (verifisere at det var Bob som sendte den). For dette trenger vi to ting: HMAC og en digital signatur.
HMAC – Hashed Message Authentication Code
HMAC er å kombinere en hashing algoritme sammen med en unik nøkkel. Bakgrunnen for dette er at Alice skal kunne verifisere integriteten i meldingen. Alice mottar plaintext meldingen og en checksum av meldingen. Hun bruker en hashing algoritme og den mottatte nøkkelen til å hashe meldingen for å se om hun får samme checmsum. Får hun samme er meldingens integritet ivaretatt. Hvis man ikke bruker den hemmelige nøkkelen sammen med hashingnen kan en angriper potensielt skifte ut meldingen og generere en egen checksum som Alice da ikke vil kunne si om kom fra Bob eller en angriper.
Digitale signaturer
Digitale signaturer benytter asymmetrisk kryptering. Målet er at brukere skal kunne signere en melding i det digitale rom og at den skal kunne verifiseres av mottaker. Dette løser utfordringen med å vite hvem som sendte hva og at sender ikke kan nekte for å ha signert meldingen.
Digitale signaturer fungerer ved at Alice bruker sin private nøkkel i en signeringsalgoritme for å generere sin signatur. Mottaker validerer signaturen ved å benytte Alice sin public (offentlige) nøkkel i en verifikasjonsalgoritme.
Nøkkelhåndtering
De forskjellige krypteringsregimene er enkle å forholde seg til. Det største problemet til krypto er nøkkelhåndtering. Hvordan distribuere nøkler, fornye nøkler, trekke tilbake nøkler, forskjellige nøkler til forskjellige soner, og tilgangsstyring til nøkler. Det er ikke mange små og mellomstore bedrifter som har penger eller kompetanse til å implementere sin egen PKI (Public Key Infrastructure) ved å kjøpe og drifte en HSM (Hardware Security Module). Disse er ofte veldig dyre og trenger sannsynligvis en HSM til hvert enkelt miljø for å oppnå defence-in-depth prinsippet.
Det som altfor mange gjør er å lagre nøkler rett på filsystemet til en maskin. Både symmetriske og asymmetriske. Dette er et problem mtp. tilgangsstyring, backup, monitorering, og vedlikehold. Mange gjør det samme med asymmetriske nøkler som ligger i sertifikater, ved at de installerer sertifikatene på en maskin. Slike fjøsløsninger gjør at man får dårlige erfaringer med krypto og ofte unngår å bruke det. Heldigvis har skyleverandørene løst mye av dette problemet for oss. Er man i skyen eller er i en migreringsprosess så ta i bruk skyens tjenester for nøkkelhåndtering fullt ut. Et eksempel er Azure Key Vault.
Litteraturliste:
Noen har forhåpentligvis fått blod på tann og da vil jeg anbefale følgende litteratur til å starte med:
«Communication Theory of Secrecy Systems». Claude Shannon’s paper fra 1949 om kryptografi i Informasjonssystemer. Publisert året etter hans legendariske paper «A Mathematical Theory of Communication». Dette er lesestoff de fleste IT studenter har vært eksponert til og fortjener gjenbesøk.
«Applied Cryptography» av Bruce Schneier. Boken ble publisert i 1996 under den første kryptokrigen og inneholder en hel del kildekode skrevet i C (dog til kryptoalgoritmer som i dag er utdaterte, men dette er fortsatt en griseviktig bok). Kryptografiprogrammer ble ansett som våpen da det kom til juridisk styring på den tiden, og det var derfor ikke lov å utvikle, dele eller selge krypteringsløsninger. En som fikk merke dette var Phil Zimmerman som skrev PGP (Pretty Good Privacy) som var det første programmet som ble populært verden over som brukte public-key kryptering. Schneier & Co. fant derimot et smutthull; det sto ingen ting om at man ikke kunne distribuere ukompilert kildekode. Zimmerman gav ut boken «PGP Source Code and Internals» i 1995.
«Introducction to Cryptography with Coding Theory» av Wade Trappe og Lawrence C. Washington.
«Handbook of Applied Cryptography» av Alfred J. Menezes, Paul C. van Oorschot og Scott A. Vanstone.
«Serious Cryptography» av Jean-Philippe Aumasson. Et moderne og fantastisk dypdykk ned i kryptoverdenen. Oppdatert og velskrevet.
«The Code Book» av Simon Singh.
«The Codebreakers» av David Kahn. Historien om kodeknekkere fra tidenes morgen og frem til…et par år siden.
Khan Academy har også et fantastisk videokurs helt gratis på nettet som jeg anbefaler på det sterkeste.
Guide: Slik utfører du sikkerhetstesting gjennom utviklingsløpet
Vil du lære mer om sikkerhet og sikkerhetstesting? I denne guiden gjennomgår sikkerhetsekspert Even Lysen hvordan du kan utføre sikkerhetstesting gjennom hele utviklingsløpet.