Historiallisten substituutiosalainten frekvenssianalyysi

Tulkitaan Atbash-, Caesar- ja Vigenère-korvaussalainten tuottamaa salakieltä frekvenssianalyysillä. Käytämme aineistona kansanedustaja Mats Löfströmin kirjallista kysymystä, joka edustaa erinomaisesti suomen kielen kirjainjakaumaa. Jos sinulla on aikaa ja mielenkiintoa, voit kokeilla nyt esiteltäviä analyysejä muilla saatavilla olevilla teksteillä.


Ladataan ensin apufunktiot, joita käytämme analyysissä. Tämän jälkeen alla oleva koodisolu hakee alkuperäisen tekstin ja asettaa tekstin laatijan tiedot.

Koodisoluissa esiintyvät funktiot, kuten alusta_t432 asettavat muuttujat oletusarvoihin. Tämä sallii koodisolujen suorittamisen haluamassaan järjestyksessä.

Inactive
from xip import lue_tiedosto_merkkijonoksi
from xip import materiaalin_freq

alkuperäinen_teksti = lue_tiedosto_merkkijonoksi(4)

# Näytetään tekstin sisältö vain ensimmäisessä solussa. Teksti on esikäsitelty.
print("Alkuperäinen teksti esikäsiteltynä:")
for i in range(0, len(alkuperäinen_teksti), 80):
   print(alkuperäinen_teksti[i:i+80])

# Laaditaan otsikko
tekstin_laatija = "Mats Löfström suomi"

# Näytetään kirjainfrekvenssit
materiaalin_freq(alkuperäinen_teksti, tekstin_laatija)

Yllä oleva kuva on vertailu suomen kielen aakkosten oletettuun jakaumaan – se onkin tuttu edellisestä osiosta. Muuttujassa alkuperäinen_teksti on tallessa merkkijonomuotoinen selväteksti. Tämän tekstin salaamme kolmella historiallisella salaimella.

Seuraavaksi näytetään Mats Löfströmin tekstin frekvenssianalyysi siten, että data on järjestetty aakkosjärjestykseen. Datan järjestämisestä tällä tavalla on hyötyä kahden ensimmäisen substituutiosalaimen kohdalla.

Inactive
from xip import tekstin_frekvenssi_aakkosjärjestyksessä, alusta_t432

# Ladataan muuttujat uudestaan, kuten ensimmäisessä koodisolussa
alkuperäinen_teksti, tekstin_laatija = alusta_t432()

# Näytetään alkuperäinen teksti
tekstin_frekvenssi_aakkosjärjestyksessä(selväteksti=alkuperäinen_teksti, otsikko=tekstin_laatija)

Nyt voimme vertailla systemaattiesti aakkosmerkeittäin sitä, miten salakielen frekvenssi vertautuu alkuperäiseen salaamattomaan kirjainjakaumaan.


Atbash-salauksen frekvenssianalyysi

Tuotetaan Mats Löfströmin suomenkielisestä kirjallisesta kysymyksestä Atbash-salattu sisältö ja tarkastellaan sitä frekvenssianalyysillä.

Inactive
# Tuodaan aputyökalut
from xip import vertaa_selväkieli_salakieli
from xip import alusta_t432

# Tuodaan kirjastosta Atbash-salain.
from xip import atbash

# Ladataan muuttujat uudestaan
alkuperäinen_teksti, tekstin_laatija = alusta_t432()

# Annetaan otsikko tulostuksiin
otsikko = tekstin_laatija + " | Atbash"

# Käytetään Atbash-salainta aiemmassa solussa haettuun tekstiin.
atbash_salattu = atbash(alkuperäinen_teksti)

# Verrataan selvätekstin ja salatekstin frekvenssejä.
vertaa_selväkieli_salakieli(selväteksti=alkuperäinen_teksti, salateksti=atbash_salattu, otsikko=otsikko)

Ylempi kuvaaja näyttää selväkielen kirjainjakauman ja alempi Atbash-salatun viestin kirjainjakauman.

Päättele vastaukset edellisen solun koodin, Atbash-salaimen toimintaperiaatteen tai kuvaajien perusteella.

Mitkä väittämistä pitävät paikkansa?

Kuten huomaat, emme ole lainkaan katsoneet tekstin sisältöä vaan tarkastelleet ainoastaan kirjainjakaumia.


Caesar-salauksen frekvenssianalyysi

Tuotetaan edellisessä tehtävässä tarkastelemastamme aineistosta salateksti Caesar-salaimella. Seuraava koodi tulostaa salaimen tuottaman histogrammin kahdella eri avaimella:

  • Ensimmäinen histogrammipari tuotetaan, kun Caesar-salainta käytetään avaimella 3.

  • Toinen histogrammipari tuotetaan, kun Caesar-salainta käytetään avaimella 4.

Tehtävänäsi on tutkia alla olevia kahdella eri avaimella tuotettuja histogrammeja ja vastata väittämiin.

Inactive
# Tuodaan apukirjastoja
from xip import merkistot
from xip import alusta_t432
from xip import vertaa_selväkieli_salakieli

# Tuodaan Caesar-salain
from xip import caesar

# Ladataan muuttujat uudestaan
alkuperäinen_teksti, tekstin_laatija = alusta_t432()

# Kerrotaan että käytössä vain isot aakkoskirjaimet
isot, _ = merkistot(suomi=True)

# Asetetaan avaimeksi 3, jota salain käyttää
avain = 3
otsikko = tekstin_laatija + " | Caesar-salain, avain="+str(avain)
caesar_salattu=caesar(alkuperäinen_teksti, aakkosto=isot, avain=avain)
vertaa_selväkieli_salakieli(alkuperäinen_teksti, caesar_salattu, otsikko)

# Tulosteen asettelua varten
print(" ")

# Asetetaan avaimeksi 4, jota salain käyttää
avain = 4
otsikko = tekstin_laatija + " | Caesar-salain, avain="+str(avain)
caesar_salattu=caesar(alkuperäinen_teksti, aakkosto=isot, avain=avain)
vertaa_selväkieli_salakieli(alkuperäinen_teksti, caesar_salattu, otsikko)

Yllä olevasta kuvasta nähdään, muun muassa että:

  • Avaimella 3 selvätekstin A-kirjaimen frekvenssi on siirtynyt salakielen D-kirjaimen frekvenssin kohdalle.

  • Avaimella 4 selvätekstin A-kirjaimen frekvenssi on siirtynyt salakielen E-kirjaimen frekvenssin kohdalle.

  • Avaimella 3 selvätekstin frekvenssikuvio kirjaimilla RSTUV on siirtynyt salakielen UVWXY-kirjainten kohdalle.

  • Avaimella 4 selvätekstin frekvenssikuvio kirjaimilla RSTUV on siirtynyt salakielen VWXYZ-kirjainten kohdalle.

Päättele vastaukset edellisen solun koodin, Caesare-salaimen toimintaperiaatteen tai kuvaajien perusteella.

Valitse oikeat väittämät:


Seuraava koodi tulostaa salaimen tuottaman histogrammin kahdella eri avaimella:

  • Ensimmäinen histogrammipari tuotetaan, kun Caesar salainta käytetään avaimella -1.

  • Toinen histogrammipari tuotetaan, kun Caesar salainta käytetään avaimella 28.

Tehtävänäsi on tutkia näillä kahdella eri avaimella tuotettuja histogrammeja ja vastata väittämiin.

Inactive
# Tuodaan apukirjastoja
from xip import merkistot
from xip import alusta_t432
from xip import vertaa_selväkieli_salakieli

# Tuodaan Caesar-salain
from xip import caesar

# Ladataan muuttujat uudestaan
alkuperäinen_teksti, tekstin_laatija = alusta_t432()

# Kerrotaan että käytössä vain isot aakkoskirjaimet
isot, _ = merkistot(suomi=True)

# Asetetaan avaimeksi -1, jota salain käyttää
avain = -1
otsikko = tekstin_laatija + " | Caesar-salain, avain="+str(avain)
caesar_salattu=caesar(alkuperäinen_teksti, aakkosto=isot, avain=avain)
vertaa_selväkieli_salakieli(alkuperäinen_teksti, caesar_salattu, otsikko)

# Tulosteen asettelua varten
print(" ")

# Asetetaan avaimeksi 28, jota salain käyttää
avain = 28
otsikko = tekstin_laatija + " | Caesar-salain, avain="+str(avain)
caesar_salattu=caesar(alkuperäinen_teksti, aakkosto=isot, avain=avain)
vertaa_selväkieli_salakieli(alkuperäinen_teksti, caesar_salattu, otsikko)

Päättele vastaukset edellisen solun koodin, Caesar-salaimen toimintaperiaatteen tai kuvaajien perusteella kun avaimina ovat -1 ja 28.

Mitkä väittämistä pitävät paikkansa?


Hieman vaativampi tehtävä Caesar-salauksella

Tämä tehtävä vaatii koodin muokkaamista ja kirjoittamista.

Luo histogrammi seuraavista selväteksti-salateksti-pareista ja päättele, mitä avainta on käytetty. Selväteksti vaihtuu joka kerta kun ajat koodin.

  • Muuttujassa selväteksti ei ole oikeaa kieltä. Se on keinotekoisesti luotu siten, että se sisältää yhtä merkkiä enemmän kuin toisia.

  • Lähtötilanteessa tätä yhtä merkkiä on tuotu 5 kappaletta enemmän kuin muita. Voit muuttaa määrän suuremmaksi, jolloin avaimen selvittäminen on helpompaa.

  • Jos avaimena on jokin äärellisen kunnan kokoa suurempi luku, lasketaan avaimesta efektiivinen avain. Tällöin jakojäännösluokka kertoo efektiivisen avaimen. Esimerkiksi jos kuntamme koko on suomen aakkoston koko ja avain on 30 saadaan siitä efektiivinen avain laskemalla \(1 \equiv 30 \pmod{29}\). Näin efektiivinen eli vaikuttava avain on 1.

Inactive
# Tuodaan valmiit funktiot
from xip import merkistot
from xip import caesar
from xip import vertaa_selväkieli_salakieli

# Kerrotaan että käytössä vain isot aakkoskirjaimet
isot, _ = merkistot(suomi=True)

selväteksti = isot*100+isot[20]*5+isot*100
salateksti = caesar(selväteksti, aakkosto=isot, avain=1234567890)

# TODO: Luo histogrammi selväteksti salateksti parista annetulla funktiolla
# 1. Poista kommentti '#'-merkki funktion edestä
# 2. Lisää funktiolle verrattava selväteksti ja salateksti kuten edellisissä esimerkeissä

#vertaa_selväkieli_salakieli( , , "Selväteksti ja salateksti")

Kun olet ottanut käyttöön kaksi edellistä funktiota ja tulostanut histogrammit, vastaa seuraaviin väittämiin.

Mitkä väittämistä pitävät paikkansa?

Voit valita useamman vaihtoehdon. Efektiivinen avain on kongruentti (mod 29) seuraavan avaimen kanssa:


Vigenère-salaimen frekvenssianalyysi

Viimeisenä korvaussalaimena katsomme miltä Vigenère-salaimella tuotettu salakirjoitus näyttää. Huomaatko salakirjoituksesta kolmen merkin kuvion? Löydätkö mitään muuta toistuvaa kuvioita?

Inactive
# Tuodaan apukirjastoja
from xip import merkistot
from xip import alusta_t432
from xip import vertaa_selväkieli_salakieli

# Tuodaan Vigenère-salain
from xip import vigenere

# Kerrotaan että käytössä vain isot aakkoskirjaimet
isot, _ = merkistot(suomi=True)

# Ladataan muuttujat uudestaan
alkuperäinen_teksti, tekstin_laatija = alusta_t432()

# Asetetaan avain
avain = 'OLI'

otsikko = tekstin_laatija + " | Vigenère-salain, avain="+ avain
vigenere_salattu=vigenere(alkuperäinen_teksti, aakkosto=isot, avain=avain)

# Näytetään selväkielen ja salakielen freknvenssit
vertaa_selväkieli_salakieli(alkuperäinen_teksti, vigenere_salattu, otsikko)

Vigenère-salaimella tuotetun salakielen analysointi vaatii kirjainryhmien analysointia. Jos emme tiedä minkä mittainen avain on, voimme yrittää etsiä eri mittaisia toistuvia kuviota.

Vigenère-salaimella korvaus tapahtui avaimen merkki-indeksien mukaisesti. Jos epäilemme avaimen olevan esimerkiksi kolmen merkin mittainen, voimme toimia seuraavasti:

  • Arvataan todennäköiset kolmen merkin avaimet, kuten esimerkiksi ’TAI’ ’VAI’ ’JOS’, ’MOI’, ’HEI’ ja niin edelleen.

  • Lasketaan syntyykö jollain avaimella selväkielinen teksti, joka noudattaa suomen kielen oletettua merkkijakaumaa.

Seuraava koodi tulostaa salakirjoituksen, joka on tuotettu Vigenère-salaimella käyttämällä avainta JOS.

Inactive
# Tuodaan apukirjastoja
from xip import merkistot
from xip import alusta_t432
from xip import vertaa_selväkieli_salakieli

# Kerrotaan että käytössä vain isot aakkoskirjaimet
isot, _ = merkistot(suomi=True)

# Tuodaan Vigenère-salain
from xip import vigenere

# Ladataan muuttujat uudestaan
alkuperäinen_teksti, tekstin_laatija = alusta_t432()

# Asetetaan avain
avain = 'JOS'

otsikko = tekstin_laatija + " | Vigenère-salain, avain="+ avain
vigenere_salattu=vigenere(alkuperäinen_teksti, aakkosto=isot, avain=avain)

# Näytetään selväkielen ja salakielen freknvenssit
vertaa_selväkieli_salakieli(alkuperäinen_teksti, vigenere_salattu, otsikko)

Vigenère-salauksen purkaminen on hieman liian työlästä johdantotasoiselle kurssille, eikä sitä varten ole varsinaista harjoitusta.

Seuraava tehtävä sisältää väittämiä Vigenère-salaimen toiminnasta.

Kumpi väittämistä pitää paikkansa?

Kumpi väittämistä pitää paikkansa? Aihetta on käsitelty jo Vigenère-salainta esitellessä. Jos et halua katsoa vastausta aikaisemmasta opetusmoduulista, voit vaihtaa koodissa avaimeksi ”AAAAAA”.


Transposition frekvenssianalyysi

Kokeillaan vielä muissa tehtävissä analysoidun tekstin muuntamista transpositiolla ja katsotaan, miltä se näyttää frekvenssianalyysillä. Pythonin random-kirjaston sample-funktio ottaa syötteeksi alkuperäisen tekstin ja palauttaa tekstin merkit satunnaisessa järjestyksessä eli kirjaimet on täysin sekoitettu.

Inactive
from random import sample
from xip import vertaa_selväkieli_salakieli

# Ladataan muuttujat uudestaan
from xip import alusta_t432
alkuperäinen_teksti, tekstin_laatija = alusta_t432()

transponoitu_teksti = sample(alkuperäinen_teksti,k=len(alkuperäinen_teksti))
vertaa_selväkieli_salakieli(selväteksti=alkuperäinen_teksti, salateksti=transponoitu_teksti, otsikko="Transponoitu")

print("Näytetään alkuperäinen teksti:")
print("".join(alkuperäinen_teksti))
print("Näytetään transponoitu teksti:")
print("".join(transponoitu_teksti))

Histogrammi ei muutu. Miksi? Yläpuolella aivan lopuksi on tulostettu sekä alkuperäinen teksti että transponoitu teksti.

Frekvenssianalyysissä transponoitu teksti näyttää samalta kuin salakielinen teksti.

Miksi histogrammi näyttää samalta selväkirjoituksen ja salakirjoituksen välillä?

Nykyiset salaimet tekevät usein sekä substituution ja permutaation, eli transposition. Useat nykyiset salaimet perustuvat subtituutio-permutaatio-verkkoihin.

Palautusta lähetetään...