Kryptologi Homework 1 Rune Højsgaard 13. februar 2007 1 Indledning Dette er besvarelsen af øvelsesopgave 1 på kurset Kryptologi 2007, Københavns Universitet. Opgaven består i at dekryptere tre ciffertekster. Til kryptoanalysen af de tre opgaver er der udviklet en række simple hjælpefunktioner der kan findes i bilag A. En elektronisk udgave af dette dokument kan hentes fra http://rune.hojsgaard.dk/datalogi/files/krypto07-opg1.pdf. 2 Øvelse 1.21 a) Substitution Cipher Givet nedenstående ciffertekst ønskes det at bestemme klarteksten, der er taget fra The Diary of Samuel Marchbanks af Robertson Davies. Cifferteksten er resultatet af at kryptere klarteksten med Substitution Cipher fra [Sti95, p. 7], hvor d K (f) = W. For at finde klarteksten benyttes strategien fra [Sti95, p. 29-32]. Frekvensen af de 26 bogstaver er gengivet i figur 1. emglosudcgdncuswysfhnsfcykdpumlwgyicoxysipjck qpkugkmgolicgincgacksnisacykzsckxecjckshysxcg oidpkzcnkshicgiwygkkgkgoldsilkgoiusigledspwzu gfzccndgyysfuszcnxeojncgyeoweupxezgacgnfglkns acigoiyckxcjuciuzcfzccndgyysfeuekuzcsocfzccnc iaczejncshfzejzegmxcyhcjumgkucy Eftersom c har den højeste frekvens formodes det, at d K (c) = E jf. sandsynlighederne i [Sti95, p. 27]. Erstattes f med W og c med E konstateres det at mønsteret WzEEn optræder tre gange i teksten. Da den første af de tre forekomster ikke har et E foran sig, antages det at WzEEn ikke er to ord f.eks. feed og dew. Givet at z og n er før/efter en vokal må de formodes at representerer konsonanter. Givet den hyppige forekomst af z og n antages det at WzEEn er ordet WHEEL, hvilket giver D K (z) = H og D K (n) = L, hvilket giver følgende: emglosudegdleuswyswhlsweykdpumlwgyieoxysipjek qpkugkmgoliegilegaekslisaeykhsekxeejekshysxeg oidpkhelkshiegiwygkkgkgoldsilkgoiusigledspwhu gwheeldgyyswushelxeojlegyeoweupxehgaeglwglkls aeigoiyekxejueiuhewheeldgyysweuekuhesoewheele iaehejleshwhejhegmxeyhejumgkuey 1
bogstav frekvens bogstav frekvens a 5 n 13 b 0 o 10 c 37 p 6 d 8 q 1 e 12 r 0 f 9 s 20 g 24 t 0 h 5 u 14 i 15 v 0 j 7 w 5 k 18 x 7 l 7 y 15 m 5 z 13 Figur 1: Frekvensen af forekomster af de 26 bogstaver i cifferteksten Her optræder WHEELdgyysW to gange, hvilket ud fra frekvenserne af g, s og y giver en formodning om, at ordet er WHEELBARROW. Denne antagelse giver altså D K (d) = B, D K (g) = A, D K (s) = O og D K (y) = R: emalooubeableuowrowhlowerkbpumlwarieoxroipjek qpkuakmaolieaileaaekolioaerkhoekxeejekohroxea oibpkhelkohieaiwrakkakaolboilkaoiuoialebopwhu AWHEELBARROWuOHELxeojLEAReoweupxeHAaEALWAlkLO aeiaoirekxejueiuhewheelbarroweuekuheooewheele iaehejleohwhejheamxerhejumakuer I første linie fremstår nu BEABLEuOwROWhLOWER, hvorfor det formodes at D K (h) = F, D K (u) = T og D K (w) = G, hvilket giver klarteksten BEABLETOGROWFLOWER. Ydermer giver frekvensen af k og klarteksten andledning til at formode at D K (k) = S. Denne substitution giver en række fragmenter af teksten; BOpGHT, hvorfor der udfra frekvensen af p formodes at D K (p) = U. GARiEo medfører at D K (i) = D og D K (o) = N. Hermed er det muligt at afkode xroipjes til xrodujes, hvilket i forhold til frekvenserne passer med ordet PRODUCES, altså d K (x) = P og d K (j) = C: emalnotbeabletogrowflowersbutmlgardenproduces qustasmanldeadleaaesoldoaershoespeecesofropea NDBUSHELSOFDEADGRASSASANlBODlSANDTODAleBOUGHT AWHEELBARROWTOHELPeNCLEAReNGeTUPeHAaEALWAlSLO aedandrespectedthewheelbarrowetestheonewheele DaEHeCLEOFWHeCHeAmPERFECTmASTER Herfra er det rimelig nemt at udlede resten af bogstaverne udfra kontekst og frekvens; d K (e) = I, d K (m) = M og d K (l) = Y, d K (q) = J og d K (a) = V, hvilket giver klarteksten: IMAYNOTBEABLETOGROWFLOWERSBUTMYGARDENPRODUCES JUSTASMANYDEADLEAVESOLDOVERSHOESPIECESOFROPEA NDBUSHELSOFDEADGRASSASANYBODYSANDTODAYIBOUGHT 2
AWHEELBARROWTOHELPINCLEARINGITUPIHAVEALWAYSLO VEDANDRESPECTEDTHEWHEELBARROWITISTHEONEWHEELE DVEHICLEOFWHICHIAMPERFECTMASTER 3 Øvelse 1.21 b) Vigenère Cipher Givet nedenstående ciffertekst ønskes det at bestemme klarteksten der er taget fra The Diary of Samuel Marchbanks af Robertson Davies. Cifferteksten er resultatet af at kryptere klarteksten med Vigenère Cipher fra [Sti95, p. 12]. For at finde klarteksten benyttes strategien fra [Sti95, p. 32-36]. kccpkbgufdphqtyavinrrtmvgrkdnbvfdetdgiltxrgud dkotfmbpvgegltgckqracqcwdnawcrxizakftlewrptyc qkyvxchkftponcqqrhjvajuwetmcmspkqdyhjvdahctrl svskcgczqqdzxgsfrlswcwsjtbhafsiasprjahkjrjumv gkmitzhfpdispzlvlgwtfplkkebdpgcebshctjrwxbafs pezqnrwxcvycgaonwddkackawbbikftiovkcgghjvlnhi ffsqesvyclacnvrwbbirepbbvfexoscdygzwpfdtkfqiy cwhjvlnhiqibtkhjvnpist For at finde nøglens længde udføres en Kasiski test. Det oftest forekommende segment er HJV der optræder fem gange i cifferteksten på positionerne (1 indekseret) 108, 126, 264 318 og 330, hvilket giver en afstand på 18, 156, 210 og 220. Den største fællesnævner for disse fire afstande er 6, hvorfor det antages at dette er længden på nøglen. For at opnå yderligere sikkerhed for at 6 er den rigtige længde kunne man beregne index of coincidence jf. [Sti95, p. 33]. For at bestemme nøglen, inddeles teksten i m = 6 strenge y i, 1 i m, hvor y i = y i y mi y 2mi. Hver y i frekvensanalyseres og efterfølgende beregnes for hver: M g = 25 i=0 p i f ig mod 26 n hvor n er længden på y i, p i sandsynlighedsfordelingen for alphabetet (engelsk), 0 g 25 og f i er frekvensen. værdierne af M g (y i ) er opsummeret i figur 2. For hvert i findes den værdi af M g der er tættest på 0.065, hvilket indikerer at g = k i. Denne værdi er markeret med firkanter i figur 2. Dette giver nøglen K = (2, 17, 24, 15, 19, 14), eller CRYPTO. Dekrypteres cifferteksten som beskrevet i [Sti95, p. 12-13] med nøglen CRYPTO fremstår følgende klartekst: ILEARNEDHOWTOCALCULATETHEAMOUNTOFPAPERNEEDEDF ORAROOMWHENIWASATSCHOOLYOUMULTIPLYTHESQUAREFO OTAGEOFTHEWALLSBYTHECUBICCONTENTSOFTHEFLOORAN DCEILINGCOMBINEDANDDOUBLEITYOUTHENALLOWHALFTH ETOTALFOROPENINGSSUCHASWINDOWSANDDOORSTHENYOU ALLOWTHEOTHERHALFFORMATCHINGTHEPATTERNTHENYOU DOUBLETHEWHOLETHINGAGAINTOGIVEAMARGINOFERRORA NDTHENYOUORDERTHEPAPER 3
i Værdien af M g (y i ) 1 0,032 0,036 0,065 0,039 0,034 0,042 0,037 0,031 0,042 0,046 0,025 0,034 0,038 0,042 0,038 0,046 0,036 0,040 0,042 0,033 0,030 0,039 0,043 0,034 0,042 0,034 2 0,038 0,039 0,049 0,042 0,040 0,036 0,045 0,030 0,027 0,036 0,045 0,031 0,035 0,048 0,040 0,033 0,036 0,071 0,037 0,030 0,029 0,036 0,030 0,038 0,046 0,037 3 0,035 0,036 0,034 0,038 0,036 0,041 0,028 0,038 0,034 0,042 0,041 0,046 0,040 0,043 0,037 0,032 0,035 0,039 0,042 0,031 0,039 0,033 0,035 0,044 0,059 0,045 4 0,045 0,038 0,044 0,037 0,037 0,038 0,031 0,033 0,039 0,037 0,037 0,051 0,041 0,031 0,035 0,066 0,037 0,030 0,039 0,041 0,025 0,035 0,041 0,033 0,035 0,044 5 0,040 0,033 0,034 0,040 0,045 0,034 0,043 0,046 0,047 0,034 0,034 0,036 0,034 0,035 0,034 0,044 0,034 0,036 0,035 0,056 0,041 0,035 0,043 0,044 0,031 0,032 6 0,042 0,038 0,037 0,042 0,039 0,027 0,033 0,039 0,037 0,034 0,048 0,035 0,025 0,037 0,070 0,042 0,032 0,032 0,039 0,033 0,040 0,041 0,035 0,037 0,039 0,048 Figur 2: værdier af M g (y i ) 4 Øvelse 1.21 c) Affine Cipher Givet nedenstående ciffertekst ønskes det at bestemme en klartekst af ukendt oprindelse. Cifferteksten er resultatet af at kryptere en klartekst med Affine Cipher fra [Sti95, p. 8-12]. For at finde klarteksten benyttes strategien fra [Sti95, p. 27-29]. Frekvensen af de 26 bogstaver er gengivet i tabel 3. kqerejebcppcjcrkieacuzbkrvpkrbcibqcarbjcvfcup kriofkpacuzqepbkrxpeiieabdkpbcpfcdccafieabdkp bcpfeqpkazbkrhaibkapcciburccdkdccjcidfuixpaff erbiczdfkabicbbenefcupjcvkabpcydccdpkbcocperk ivkscpicbrkijpkabi De mest frekvente bogstaver er c og b, hvorfor det gættes at c er E og b er T. Altså e K (4) = 2 og e K (19) = 1, hvilket giver føgende lineære ligninger: 4a b = 2 19a b = 1 4
bogstav frekvens bogstav frekvens a 13 n 1 b 21 o 2 c 32 p 20 d 9 q 4 e 13 r 12 f 10 s 1 g 0 t 0 h 1 u 6 i 16 v 4 j 6 w 0 k 20 x 2 l 0 y 1 m 0 z 4 Figur 3: Frekvensen af forekomster af de 26 bogstaver i cifferteksten Den unikke løsning til Z 26 kan nu findes ved at substituerer a med b i den ene ligning: 4a b = 2 b = 22a 2 19a b = 1 19a 22a 2 = 1 15a 2 = 1 11a = 1 a = 19 4 19 b = 2 24 b = 2 b = 4 Da størstefællesnævner for a og 26 er 1, er nøglen K = (19, 4) lovlig og den afprøves på cifferteksten for at undersøge om klarteksten er en meningsfuld tekst. Jf. [Sti95, p. 10] så er 19 1 = 11 i Z 26 hvilket giver: hvilket giver klarteksten: d K (y) = 11(y 4) = 11y 8; OCANADATERREDENOSAIEUXTONFRONTESTCEINTDEFLEUR ONSGLORIEUXCARTONBRASSAITPORTERLEPEEILSAITPOR TERLACROIXTONHISTOIREESTUNEEPOPEEDESPLUSBRILL ANTSEXPLOITSETTAVALEURDEFOITREMPEEPROTEGERANO SFOYERSETNOSDROITS Dette er den Canadiske nationalsang som er skrevet på fransk, hvorfor det har været heldigt, at frekvenstabellen for det engelske sprog kunne anvendes. 5
5 Litteratur [Sti95] Douglas R. Stinson. Cryptography - Theory and Practice. CRC Press Inc, 1995. 6
7 A Kildekode ï» u s i n g System ; u s i n g System. C o l l e c t i o n s. G e n e r i c ; u s i n g System. Text ; u s i n g System. C o l l e c t i o n s ; u s i n g System. Text. R e g u l a r E x p r e s s i o n s ; namespace K r y p t o l o g i 2 0 0 7 c l a s s Program // the a l p h a b e t s t a t i c char [ ] a l p h a b e t = new char [ ] 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 ; //Very crude char > index f u n c t i o n s t a t i c int alphabetindex ( char c ) int i ; f o r ( i = 0 ; i < 26; i) i f ( a l p h a b e t [ i ] == c ) break ; return i ; // p r o b a b i l i t y o f occurance ( e n g l i s h ) s t a t i c double [ ] l e t t e r p r o b = new double [ ] 0. 0 8 2, 0. 0 1 5, 0. 0 2 8, 0. 0 4 3, 0. 1 2 7, 0. 0 2 2, 0. 0 2 0, 0. 0 6 1, 0. 0 7 0, 0. 0 0 2, 0. 0 0 8, 0. 0 4 0, 0. 0 2 4, 0. 0 6 7, 0. 0 7 5, 0. 0 1 9, 0. 0 0 1, 0. 0 6 0, 0. 0 6 3, 0. 0 9 1, 0. 0 2 8, 0. 0 1 0, 0. 0 2 3, 0. 0 0 1, 0. 0 2 0, 0. 0 0 1 ; //Performs Kasiski t e s t on a string. // Prints the recurring segment, index of f i r s t occurance and recurrance, and the distance between p r i v a t e s t a t i c void K a s i s k i T e s t ( s t r i n g t e x t ) Hashtable found = new Hashtable ( ) ; Console. Write ( " C i p h e r t e x t \ t a t, r e p e a t a t \ t d i s t a n c e \ r \n" ) ; Console. Write ( " s t r i n g \ t \ t ( i n d e x ) \ r \n\ r \n" ) ; f o r ( int s t a r t = 0 ; s t a r t < t e x t. Length 3 ; s t a r t ) f o r ( int keylength = 3 ; keylength < ( text. Length s t a r t ) ; k e y l e n g t h) s t r i n g segment = t e x t. S u b s t r i n g ( s t a r t, k e y l e n g t h ) ; i f ( found. Contains ( segment ) ) break ; f o r ( int t e s t = s t a r t k e y l e n g t h ; t e s t < t e x t. Length keylength 1 ; t e s t) i f ( segment == t e x t. S u b s t r i n g ( t e s t, k e y l e n g t h ) ) Console. Write ( segment "\ t \ t " s t a r t ", " t e s t "\ t \ t " ( t e s t s t a r t ) " \ r \n" ) ; i f (! found. ContainsKey ( segment ) ) found. Add( segment, n u l l ) ; // C a l c u l a t e s binomial c o e f f i c i e n t public s t a t i c int Binom ( int n, int k ) int [ ] b = new int [ n 1 ] ; b [ 0 ] = 1 ; f o r ( int i = 1 ; i <= n ; i ) b [ i ] = 1 ; f o r ( int j = i 1 ; j > 0 ; j ) b [ j ] = b [ j 1 ] ; return b [ k ] ; // Counts occourances o f a character in a s t r i n g p r i v a t e s t a t i c int C o u n t L e t t e r s ( char c, s t r i n g t e x t ) return t e x t. Length t e x t. Replace ( c. ToString ( ), "" ). Length ; // Prints occurances of each char in char [ ] alphabet in a given s t r i n g p r i v a t e s t a t i c int [ ] P r i n t O c c u r a n c e ( s t r i n g t e x t, b o o l s i l e n t ) int [ ] o c c V e c t o r = new int [ 2 6 ] ; int index = 0 ; f o r e a c h ( char c i n a l p h a b e t ) int occ = C o u n t L e t t e r s ( c, t e x t ) ; occvector [ index ] = occ ; i n d e x; i f (! s i l e n t ) Console. Write ( c " : " occ "\ r \n" ) ; return occvector ; // Calculates M_g according to Stinson p. 35. p r i v a t e s t a t i c void Mg( s t r i n g y ) int [ ] occ = P r i n t O c c ur a n c e ( y, t r u e ) ; int delimeter = 9 ; // only used f o r l a y o u t f o r ( int g = 0 ; g < 26 ; g) double mgi = 0 ; f o r ( int i = 0 ; i < 2 6 ; i ) mgi = ( l e t t e r p r o b [ i ] ( double ) occ [ ( ig ) %26]) / ( double ) y. Length ; Console. Write ( " 0 : F3", mgi ) ; Console. Write ( " & " ) ; i f ( g1 % d e l i m e t e r == 0 ) Console. Write ( "\ r \n" ) ;
8 // Encrypts and d e c r y p t s s t r i n g s with the vignã re Cipher //Assumes lower case string i f decrypting and upper case i f encrypting p r i v a t e s t a t i c s t r i n g V i g e n e r e C i p h e r ( s t r i n g t e x t, s t r i n g key, bool d e c r y p t i n g ) s t r i n g r e t u r n t e x t = S t r i n g. Empty ; //Add key i f encrypting, subtract i f decrypting int swich = 1 ; i f ( d e c r y p t i n g ) swich = 1; //Change text to lower case to use the alphabet [ ] and the alphabetindex method. i f (! d e c r y p t i n g ) t e x t = t e x t. ToLower ( ) ; char [ ] chars = text. ToCharArray ( ) ; char [ ] keychars = key. ToCharArray ( ) ; //Apply encryption to p l a i n t e x t / decrypt c i p h e r t e x t f o r ( int i = 0 ; i < t e x t. Length ; i ) int j = ( a l p h a b e t I n d e x ( c h a r s [ i ] ) swich a l p h a b e t I n d e x ( k e y c h a r s [ i % key. Length ] ) ) % 2 6 ; i f ( j <0) j = 2 6 ; r e t u r n t e x t = a l p h a b e t [ j ] ; //Change case to upper i f decrypting i f ( d e c r y p t i n g ) r e t u r n t e x t = r e t u r n t e x t. ToUpper ( ) ; return re turntex t ; // Encrypts and d e c r y p t s s t r i n g s with the Affine Cipher in Z_ 26 //Assumes lower case string i f decrypting and upper case i f encrypting p r i v a t e s t a t i c s t r i n g A f f i n e C i p h e r ( s t r i n g t e x t, int a, int b, bool d e c r y p t i n g ) s t r i n g r e t u r n t e x t = S t r i n g. Empty ; //Change text to lower case to use the alphabet [ ] and the alphabetindex method. i f (! d e c r y p t i n g ) t e x t = t e x t. ToLower ( ) ; char [ ] chars = text. ToCharArray ( ) ; i f ( d e c r y p t i n g ) //a^ 1... I dont know how to compute i t in modulo so I ve j u s t provided a t a b l e switch ( a ) case 1 : a = 1 ; break ; case 3 : a = 9 ; break ; case 5 : a = 2 1 ; break ; case 7 : a = 1 5 ; break ; case 9 : a = 3 ; break ; case 1 1 : a = 1 9 ; break ; case 1 5 : a = 7 ; break ; case 1 8 : a = 2 3 ; break ; case 1 9 : a = 1 1 ; break ; case 2 1 : a = 5 ; break ; case 2 3 : a = 1 8 ; break ; default : return "" ; f o r ( int i = 0 ; i < t e x t. Length ; i ) int y = a l p h a b e t I n d e x ( c h a r s [ i ] ) ; int j = ( a ( y b ) ) % 2 6 ; i f ( j < 0 ) j = 2 6 ; r e t u r n t e x t = a l p h a b e t [ j ] ; //Change case to upper case r e t u r n t e x t = r e t u r n t e x t. ToUpper ( ) ; e l s e // encrypting f o r ( int i = 0 ; i < t e x t. Length ; i ) int y = a l p h a b e t I n d e x ( c h a r s [ i ] ) ; int j = ( a y b ) % 2 6 ; i f ( j < 0 ) j = 2 6 ; r e t u r n t e x t = a l p h a b e t [ j ] ; return ret urntex t ; // Calculates M_g for a l l y_i given a keylength ( use KasiskiTest to f i n d the // k e y l e n g t h ). p r i v a t e s t a t i c void C a l c u l a t e A l l M g ( s t r i n g y, int k e y l e n g t h ) s t r i n g [ ] ys = new s t r i n g [ k e y l e n g t h ] ; ys. I n i t i a l i z e ( ) ; char [ ] c h a r s = y. ToCharArray ( ) ; f o r ( int i = 0 ; i < c h a r s. Length ; i ) ys [ i%k e y l e n g t h ] = c h a r s [ i ] ; Console. Write ( " i \ t v a l u e o f M_g (y_ i ) \ r \n" ) ; f o r ( int i = 0 ; i < k e y l e n g t h ; i ) Console. Write ( "\ r \n" ) ;
9 Console. Write ( i 1 "\ t& " ) ; Mg( ys [ i ] ) ; Console. Write ( "\ r \n" ) ; s t a t i c void Main1 ( s t r i n g [ ] a r g s ) Console. Write ( " E x e r c i s e 1. 2 1 a ) \ r \ n L e t t e r o c c o u r a n c e s : \ r \n" ) ; P r i n t O c c u r a n c e ( " emglosudcgdncuswysfhnsfcykdpumlwgyicoxysipjck " " q p k u g k m g o l i c g i n c g a c k s n i s a c y k z s c k x e c j c k s h y s x c g " " o i d p k z c n k s h i c g i w y g k k g k g o l d s i l k g o i u s i g l e d s p w z u " " g f z c c n d g y y s f u s z c n x e o j n c g y e o w e u p x e z g a c g n f g l k n s " " a c i g o i y c k x c j u c i u z c f z c c n d g y y s f e u e k u z c s o c f z c c n c " " i a c z e j n c s h f z e j z e g m x c y h c j u m g k u c y ", f a l s e ) ; Console. WriteLine ( "\ r \n\ r \ n E x e r c i s e 1. 2 1 b ) \ r \ n K a s i s k i t e s t : \ r \n" ) ; KasiskiTest ( " kccpkbgufdphqtyavinrrtmvgrkdnbvfdetdgiltxrgud " " dkotfmbpvgegltgckqracqcwdnawcrxizakftlewrptyc " " qkyvxchkftponcqqrhjvajuwetmcmspkqdyhjvdahctrl " " svskcgczqqdzxgsfrlswcwsjtbhafsiasprjahkjrjumv " " gkmitzhfpdispzlvlgwtfplkkebdpgcebshctjrwxbafs " " pezqnrwxcvycgaonwddkackawbbikftiovkcgghjvlnhi " " ffsqesvyclacnvrwbbirepbbvfexoscdygzwpfdtkfqiy " " cwhjvlnhiqibtkhjvnpist " ) ; Console. WriteLine ( "\ r \n\ r \ n E x e r c i s e 1. 2 1 b ) \ r \ n C a l c u a l t i n g Mg\ r \n" ) ; C a l c u l a t e A l l M g ( " kccpkbgufdphqtyavinrrtmvgrkdnbvfdetdgiltxrgud " " dkotfmbpvgegltgckqracqcwdnawcrxizakftlewrptyc " " qkyvxchkftponcqqrhjvajuwetmcmspkqdyhjvdahctrl " " svskcgczqqdzxgsfrlswcwsjtbhafsiasprjahkjrjumv " " gkmitzhfpdispzlvlgwtfplkkebdpgcebshctjrwxbafs " " pezqnrwxcvycgaonwddkackawbbikftiovkcgghjvlnhi " " ffsqesvyclacnvrwbbirepbbvfexoscdygzwpfdtkfqiy " " cwhjvlnhiqibtkhjvnpist ", 6 ) ; Console. WriteLine ( "\ r \n\ r \ n E x e r c i s e 1. 2 1 b ) \ r \ ndecrypting : \ r \n" ) ; s t r i n g d e c r y p t = V i g e n e r e C i p h e r ( " kccpkbgufdphqtyavinrrtmvgrkdnbvfdetdgiltxrgud " " dkotfmbpvgegltgckqracqcwdnawcrxizakftlewrptyc " " qkyvxchkftponcqqrhjvajuwetmcmspkqdyhjvdahctrl " " svskcgczqqdzxgsfrlswcwsjtbhafsiasprjahkjrjumv " " gkmitzhfpdispzlvlgwtfplkkebdpgcebshctjrwxbafs " " pezqnrwxcvycgaonwddkackawbbikftiovkcgghjvlnhi " " ffsqesvyclacnvrwbbirepbbvfexoscdygzwpfdtkfqiy " " c w h j v l n h i q i b t k h j v n p i s t ", " c r y p t o ", t r u e ) ; //Lame Console. Write cant print the whole s t i r i n g at once... f o r ( int i = 0 ; i < decrypt. Length ; i = 256) int end = ( i 256 > decrypt. Length? decrypt. Length i : 256) ; Console. Write ( d e c r y p t. S u b s t r i n g ( i, end ) ) ; Console. WriteLine ( "\ r \n\ r \ n E x e r c i s e 1. 2 1 c ) \ r \ noccurances : \ r \n" ) ; P r i n t O c c u r a n c e ( " kqerejebcppcjcrkieacuzbkrvpkrbcibqcarbjcvfcup " " kriofkpacuzqepbkrxpeiieabdkpbcpfcdccafieabdkp " " bcpfeqpkazbkrhaibkapcciburccdkdccjcidfuixpaff " " erbiczdfkabicbbenefcupjcvkabpcydccdpkbcocperk " " i v k s c p i c b r k i j p k a b i ", f a l s e ) ; Console. WriteLine ( "\ r \n\ r \ n E x e r c i s e 1. 2 1 c ) \ r \ ndecypting : \ r \n" ) ; Console. Write ( A f f i n e C i p h e r ( " kqerejebcppcjcrkieacuzbkrvpkrbcibqcarbjcvfcup " " kriofkpacuzqepbkrxpeiieabdkpbcpfcdccafieabdkp " " bcpfeqpkazbkrhaibkapcciburccdkdccjcidfuixpaff " " erbiczdfkabicbbenefcupjcvkabpcydccdpkbcocperk " " i v k s c p i c b r k i j p k a b i ", 1 9, 4, t r u e ) ) ; Console. Read ( ) ;