- CS-EJ4404
- 8. Julkisen avaimen menetelmät
- 8.2 Suuret luvut
Suuret luvut¶
Kurssilla on toistaiseksi käytetty lähes yksinomaan ”pienehköjä ”numeroita ja lukuja. Suurempiin lukuihin on aikaisemmin vain viitattu.
Pienehköt luvut ja turvataso¶
”Pienehkö” luku on esimerkiksi 128-bittinen luku.
Olemme käyttäneet 128-bittistä lukua muun muassa avaimena.
128-bittinen avain voidaan esittää lukuna, jossa on 39-numeroa.
Esimerkiksi 128-bittisen 39-numeroisen luvun 215826290122223003264819486280856312625
binääriesitys on
0b10100010010111101010000110101001100010100111101111100011110110011110001111010010010100010001101011000110101111110001101100110001
Käsittelimme jo aiemmin turvatasoa. Turvataso määrittää todennäköisyyden, että raa’alla voimalla tapahtuva laskenta riittää murtamaan salaimen.
Olemme tähän mennessä käyttäneet symmetrisiä salaimia, jossa 128-bittinen avain tuottaa 128-bittisen turvatason.
Kun katsot edellistä 128-bittistä bittijonoa, se voi auttaa hahmottamaan, mitä 128-bittisellä turvallisuudella tarkoitetaan:
Hyökkääjän pitää kokeilla kaikkia avainvaihtoehtoja murtaakseen salaimen.
128 bitin tapauksessa tilanne on sama, kuin jos kokeilisi mikä luku numeroiden 0 ja \(2^{128}-1\) (eli 340282366920938463463374607431768211455) välillä on oikea avain.
Symmetrisissä salaimissa avaimen koon kasvattaminen 128 bitistä ja 129 bittiin kaksinkertaistaa kokeiltavan avainavaruuden koon. Tällöin avainavaruuden koko on \(2^{129}\) ja suurin sillä saatava luku on 680564733841876926926749214863536422911. Samalla tuplaamme avaimen murtamiseen tarvittavan ajan tai raa’alla voimalla tapahtuvaan laskentaan vaadittavan laskentakapasiteetin.
Laskimme jo aiemmin, että tällaisissa tapauksissa suurellakin laskentakapasiteetilla vie valtavasti aikaa kokeilla kaikki mahdolliset avaimet.
Suurten lukujen hahmottaminen¶
Suuria lukuja on todella vaikea hahmottaa. Edellisessä kappaleessa 128-bittinen luku esitellään ”pienehkönä”. Mikä on sitten suurehko luku ja mihin se vertautuu?
Esimerkkinä suuresta luvusta voidaan mainita se, että atomien määrän maapallossa on arvioitu olevan noin \(1.3 \cdot 10^{50}\) eli noin \(2^{167}\) kappaletta. Tämä tarkoittaa siis sitä, että jos salaimessa käytettäisiin 167-bittisiä avaimia, silloin oikean avaimen löytäminen olisi verrattavissa tietyn atomin löytämiseen maapallosta satunnaisesti kokeilemalla! Nykyään usein käytetään avaimia, joiden turvataso on 256 bittiä. Symmetrisissä salaimissa tällainen turvataso vastaa 256-bittistä avainta. Näin ollen avainvaihtoehtojen määrä on vielä huomattavasti suurempi.
Julkisen avaimen järjestelmissä käytettävät luvut ovat usein vielä huomattavasti edellä mainittuja lukuja suurempia. Joudumme käyttämään suurempia lukuja saavuttaaksemme tietyn turvatason. Esimerkiksi, jotta myöhemmin esiteltävän RSA-järjestelmän tapauksessa saavutettaisiin 128-bittinen turvataso, on käytettävä 3072-bittisiä lukuja. Julkisen avaimen järjestelmien tapauksessa avainten koko ja saavutettu turvataso eivät siis enää ole sama asia. Tyypillisesti julkisen avaimen järjestelmissä täytyy käyttää huomattavasti suurempia avaimia, kuin mikä niillä saavutettava turvataso on.
Tekijöihin jako¶
RSA:n tapauksessa turvallisuus perustuu siihen, että suuria lukuja on erittäin vaikea jakaa tekijöihin. Etsimme siis niitä alkulukuja, joiden tulona jokin luku esiintyy.
Jos esimerkiksi otetaan luku 77, löytyvät sen alkulukutekijät 7 ja 11 välittömästi ilman apuvälineitä. Alkuluvuilla on tärkeä rooli lukuteoriassa. Samoin esimerkiksi 46127 on sekin vielä ratkaistavissa melko nopeasti: 193 ja 239. Ihmisen rajat jakaa lukuja tekijöihin tulevat vastaan melko pian lukujen kasvaessa. Tietokoneella lukujen jako tekijöihin voidaan suorittaa helpommin. Tietokoneidenkin rajat tulevat kuitenkin vastaan, kun käytetään riittävän suuria lukuja.
Tekijöihin jakoon on olemassa tehokkaampia menetelmiä kuin vain kaikkien vaihtoehtojen kokeileminen. Näiden menetelmien yksityiskohtainen tarkastelu ei kuulu enää tämän kurssin aihepiiriin, mutta lisätietoa löytyy esimerkiksi Wikipediasta. Tämän hetken parhaana algoritmina pidetään yleistä lukukuntaseulaa.
Oheisessa kuvassa näytetään esimerkki suuren numeron jakamisesta tekijöihin. Luku on 240-numeroinen (eli 795-bittinen) ja kului 900 vuotta laskenta-aikaa jakaa se tekijöihin. Laskenta suoritettiin useilla tietokoneilla rinnakkain, joten varsinaista kalenteriaikaa tekijöihinjakoon ei kulunut näin paljon. Luku jaettiin tekijöihin vuonna 2019.
Vuonna 2021 ennätys rikottiin jakamalla 250-numeroinen (eli 829-bittinen) luku tekijöihin. Tähän kului 2700 vuotta laskenta-aikaa.
Miten suurilla luvuilla lasketaan?¶
Kuten jo mainittiin, RSA:ssa käytetyt avaimet ovat vielä paljon suurempia lukuja. Pienin nykyään suositeltu koko on 2048 bittiä.
Esimerkiksi eräässä haasteessa (ns. RSA-2048 challenge), tehtävänä on jakaa tekijöihin seuraava luku:
Koska käsiteltävät luvut ovat todella suuria, on niiden käsittely jo normaalissa tiedon salaamisessa ja purkamisessakin haastavaa. Tavallinen laskuoperaatio näissä järjestelmissä on potenssiin korotus ja modulo.
Seuraava yhtälö on yleinen esimerkki laskennasta, jossa luku \(x\) korotetaan potenssiin \(e\), jonka tuloksesta otetaan modulo \(n\) .
\(y = x^e \pmod{n}\),
RSA-menetelmässä lukujen \(e\), \(n\) ja \(x\) oletetaan olevan samaa suuruusluokkaa (esim. 3072 bitin kokoisia). Tämä lasku voidaan laskea tehokkaasti perättäisillä kertolaskuilla moduloon \(n\) . Tällöin vaadittava kertolaskujen määrä on korkeintaan kaksi kertaa eksponentin pituus bitteinä. Algoritmissa eksponentti esitetään ensin binääriesityksenä.
Laskentaesimerkki¶
Tehdään yksi esimerkkilaskenta pienillä luvuilla. Sama laskenta toimii myös suurilla luvuilla. Näytämme, miten seuraava laskenta toteutetaan algoritmisesti oikein.
Kuten matemaatikot aloittavat, olkoon:
\(n=17\)
\(x=3\)
\(e=10\), jonka binääriesitys on
0b1010
.Merkitään eksponentin bittimäärää \(t\):llä eli nyt \(t=4\).
\(i\) saa arvoja \(i=0,\ldots,t-1\)
Algoritmissa lasketaan ensin \(x^{2^i}\) eli nyt lasketaan:
Kongruenssi ilmaisi siis jakojäännösluokkan modulorenkaassa.
Tämän jälkeen kerrotaan yllä lasketut välitulokset \(x^{2^i}\):t keskenään, jos eksponentin \(e\) bitti \(i\) on ykkönen.
Muistetaan että tietokonemaailmassa järkevä indeksointi alkaa nollasta.
Eli tässä tapauksessa, kun eksponentin \(e\) bitit olivat 1010
lasketaan:
\(y = x^{2^1} \cdot x^{2^3} \pmod{17} = 9 \cdot 16 \pmod{17} = 144 \pmod{17} = 8\).
Näin pienen laskun voi laskea vielä tavallisella laskimella ja voitkin kokeilla, että laskimella todella saadaan sama tulos kuin yllä olevalla algoritmilla. Tavallisella laskimella ei kuitenkaan voi enää laskea laskuja, jotka tapahtuvat esim. 3072-bittisillä luvuilla!
Teemme alla saman laskennan Python-koodilla. Voit hyödyntää tätä koodisolua alla olevassa tehtävässä, jollet halua käyttää kynää ja paperia.
import math
# Alustetaan muuttujat
n = 17
x = 3
e = 10
# Lasketaan e:stä seuraavat asiat
e_bitit = bin(e).split('b')[1]
e_pituus = len(e_bitit)
# Näytetään muuttujat
print("n = {}; x = {} ; e = {}".format(n, x, e))
print("e:n bittikuvio = {}, jolloin t = {}".format(e_bitit, e_pituus))
print("Tällöin i käy 0:sta {}:een".format(e_pituus-1))
# lasketaan x^2^i välitulokset talteen
välitulokset = []
for i in range(e_pituus):
välitulokset.append(x**(2**i)%n)
print("Välitulokset ovat:", välitulokset)
# Suoritetaan laskenta loppuun, tarkistetaan e:n bitit ja lasketaan tulo.
print("eksponentin bitit:",e_bitit)
tulos = 1
# Vähiten merkitsevä bitti (LSB) on bittijonossa "oikealla".
# Tällöin oikeanpuoleisin e:n bitti on järjestysnumeroltaan "nolla".
# Käymme e:n bitit läpi oikealta vasemmalle.
for i, bitti in enumerate(reversed(e_bitit)):
# Jos tarkasteltava bitti on 1, kerrotaan välitulos mukaan tulokseen mod(n)
if bitti == '1':
tulos = (välitulokset[i] * tulos)%n
else:
pass
print("Ja laskennan tulos on:", tulos)
Yhteenveto¶
Nyt ymmärrämme, mitä kryptografiassa tarkoitetaan suurilla luvuilla.
Vaikka symmetristen salainten 128-bitin avaimia on paljon, ne ovat kuitenkin ”pienehköjä” lukuja verrattuna suuriin lukuihin.
Epäsymmetrisissä menetelmissä avaimien pituudet voivat olla tuhansia bittejä.
Epäsymmetrisissä menetelmissä turvataso ja avaimen pituus eivät ole enää sama asia.
Osaamme käytännössä laskea potenssiinkorotukset modulorenkaan sisällä nopealla tavalla.
Seuraavaksi sovellamme juuri oppimiamme tietoja Diffie–Hellman-avaintenvaihtoprotokollan ja RSA-menetelmän kanssa.