R-ohjelmointi.org

Tilastotieteellistä ohjelmointia R-kielellä

Lisää klassisia salausmenetelmiä

Edellisessä postauksessa esiteltiin muutamia klassisia salakirjoitusmenetelmiä. Jos Singhin kirja ei ole saatavilla, myös Crypto Corner perehdyttää klassisiin salakirjoitusmenetelmiin. Tutustumme tässä artikkelissa hieman monimutkaisempiin klassisiin salakirjoitusmenetelmiin.

Vigenère

Caesar-salakirjoitus oli aikoinaan tehokas, mutta myöhemmin auttamattomasti liian heikko. Samaa ideaa voidaan kuitenkin laajentaa siten, että salakirjoituksessa käytetään apuna koodiavainta, joka kertoo, millä monista erilaisista Caesar-tyyppisistä salakirjoituksista kyseinen merkki salataan. Tämä menetelmä tunnetaan Vigenèren salakirjoituksena. Menetelmä perustuu seuraavanlaiseen Vigenèren neliöön:

   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o   p   q   r   s   t   u   v   w   x   y   z   å   ä   ö  
a "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö"
b "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a"
c "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b"
d "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c"
e "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d"
f "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e"
g "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f"
h "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g"
i "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h"
j "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i"
k "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
l "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k"
m "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
n "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m"
o "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n"
p "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o"
q "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p"
r "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q"
s "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r"
t "t" "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
u "u" "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t"
v "v" "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u"
w "w" "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v"
x "x" "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w"
y "y" "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x"
z "z" "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y"
å "å" "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
ä "ä" "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å"
ö "ö" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "å" "ä"

Oletetaan että salattava teksti on ’kirja’, ja avain on ’ankka’. Avainta käyttäen päätellään kullekin salattavan tekstin kirjaimelle rivi, jolta vastine luetaan. Koska avaimen ensimmäinen kirjain on a, salataan kirjain k siis taulukon ensimmäiseltä riviltä ja k-kirjainta vastaavalta sarakkeelta löytyvällä kirjaimella, joka on k. Näin jatketaan kunnes koko viesti on salattu. Jos viesti on pidempi kuin avain, toistetaan avainta, kunnes se kattaa koko viestin pituuden.

Esimerkkimme näyttäisi kokonaisuudessaan seuraavalta:

viesti  kirja
avain   ankka
salattu kväta

Vigenèren salakirjoitus on helppo toteuttaa tietokoneella, alla R-kielinen versio:

# Vigenere
make_vigenere_square <- function(let=NULL) {
   if(is.null(let)) {
      let  <- c(letters, "å", "ä", "ö")
   }
   vine <- matrix(ncol=length(let), nrow=length(let))
   colnames(vine) <- let
   rownames(vine) <- let
   for(i in 1:length(let)) {
      vine[i,] <- encrypt_caesar(paste(let, collapse=""), let[i])
   }
   return(vine)
}
 
 
encrypt_vigenere <- function(text, avain, let=NULL) {
   vige <- make_vigenere_square(let = let)
   key <- rep(strsplit(avain, "")[[1]], length.out=nchar(text))
   text2 <- tolower(strsplit(text, "")[[1]])
 
   rind <- match(key, rownames(vige))
   cind <- match(text2, colnames(vige))
 
   res <- rep(NA, length(rind))
   for(i in 1:length(rind)) {
      res[i] <- vige[rind[i], cind[i]]
   }
 
   res[is.na(res)]<-" "
   return(res)
}
 
 
decrypt_vigenere <- function(text, avain, let=NULL) {
   vige <- make_vigenere_square(let = let)
   key <- rep(strsplit(avain, "")[[1]], length.out=nchar(text))
   text2 <- tolower(strsplit(text, "")[[1]])
 
   rind <- match(key, rownames(vige))
   res <- rep(NA, length(rind))
   for(i in 1:length(rind)) {
       res[i] <- match(text2[i], vige[rind[i],])
   }
   res <- colnames(vige)[res]
   res[is.na(res)]<-" "
   return(res)
}

Koodin käyttö tapahtuu seuraavasti (vaatii encrypt_caesar()-funktion edellisestä postauksesta):

text <- "Aluksi kirjoitettujen viestien harvinaisuus suojasi viestejä."
crypto <- paste(encrypt_vigenere(text, "abba"), collapse="")
print(crypto)
# [1] "anwksk kitloivgttwlen xieuviep hatxincksuwu swqjauk vkgstglä "
paste(decrypt_vigenere(crypto, "abba"), collapse="")
# [1] "aluksi kirjoitettujen viestien harvinaisuus suojasi viestejä "

Autokey-koodi

Autokey-menetelmässä viestin salaamiseen käytetään viestiä itsessään siten, että sen alkuun on ensin lisätty jokin aiemmin sovittu sana. Olkoon viestin jälleen ”kirje”, ja sovittu koodisana ”ja”. Tällöin viesti koodattaisiin Vigenèren salakirjoituksella, jossa avaimena olisi ”jakir”. Tällöin kaksi ensimmäistä kirjainta dekryptattaisiin sillä tiedolla, että ne on kryptattu sanalla ”ja”, ja loput kirjaimet sitten näin selvinneen viestin alkupäästä lukien seuraavilla kirjaimilla.

Autokey-salauksen toteutus R-kielellä voi olla esimerkiksi seuraavanlainen:

# Autokey
encrypt_autokey <- function(text, avain="ja", let=NULL) {
   vige <- make_vigenere_square(let = let)
   text <- gsub("[[:punct:]]|[[:space:]]", "", text)
   avain <- gsub("[[:punct:]]|[[:space:]]", "", avain)
 
   key <- tolower(strsplit(paste0(avain, text), "")[[1]][1:nchar(text)])
   text2 <- tolower(strsplit(text, "")[[1]])
 
   rind <- match(key, rownames(vige))
   cind <- match(text2, colnames(vige))
 
   res <- rep(NA, length(rind))
   for(i in 1:length(rind)) {
      res[i] <- vige[rind[i], cind[i]]
   }
 
   res[is.na(res)]<-" "
   return(res)
}
 
 
decrypt_autokey <- function(text, avain="ja", let=NULL) {
   vige <- make_vigenere_square(let = let)
 
   res <- rep(NA, nchar(text))
   key <- strsplit(avain, "")[[1]]
   text2 <- tolower(strsplit(text, "")[[1]])
 
   rind <- match(key, rownames(vige))
   for(i in 1:length(key)) {
      res[i] <- match(text2[i], vige[rind[i],])
   }
   res[1:length(key)] <- colnames(vige)[res[1:length(key)]]
 
   for(j in 1:(length(text2)-length(key))) {
      rind <- match(res[j], rownames(vige))
      res[j+length(key)] <- colnames(vige)[match(text2[j+length(key)], vige[rind,])]
   }
 
   return(res)
}

Koodia käytetään seuraavasti:

text <- "Aluksi kirjoitettujen viestien harvinaisuus suojasi viestejä."
avain <- "ja"
crypto<-paste(encrypt_autokey(text, avain=avain), collapse="")
print(crypto)
# [1] "jluvjsöqärcremjxköywzvzåxåxvlnyvzfivsöjjjjdaoäikqzåxwöc"
 
decrypto <- paste(decrypt_autokey(crypto, "ja"), collapse="")
print(decrypto)
# [1] "aluksikirjoitettujenviestienharvinaisuussuojasiviestejä"

Github

Näiden salausmenetelmien koodi löytyy myös Githubista.


Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *

Category