Warning: Missing argument 2 for wpdb::prepare(), called in /home/stromber/public_html/kryptoblog/wp-content/plugins/wp-super-edit/wp-super-edit.core.class.php on line 109 and defined in /home/stromber/public_html/kryptoblog/wp-includes/wp-db.php on line 1222
Pythongeneratorer och RC4 » Kryptoblog

Pythongeneratorer och RC4

April 7th, 2008 by Joachim Strömbergson Leave a reply »

Ett litet erkännande: Jag gillar programspråket Python.

Jag började använda Python så smått för några år sedan, och sedan dess har användningen bara ökat. Jag använder i dag Python bland annat till att bygga program som genererar parametriserade hårdvarubeskrivningar (i Verilog eller VHDL), exempelvis av krypton.

Ofta har jag även ett Pythonskal igång i ett terminalfönster och använder den som en miniräknare, genererar små sekvenser, testhackar m.m. Jag upplever att Python har gjort att mina konstruktioner inte bara är mycket bättre, utan att jag arbetar mer effektivt och är mer produktiv.

Några av de saker jag gillar med Python är dess objektorientering, att det är lätt att komma igång och att det känns som att det finns en organiserad tanke och struktur hur kommandon etc är uppbyggda. Det funkar som jag tror att det gör. Men en av de viktigaste aspekterna är (anser jag) att programmen blir läsbara.

Jag kan läsa program jag skrev för flera veckor sedan och fatta vad det gör och jag kan läsa andras kod. (I det här läget brukar jag peka på Trac och dess kod som exempel på hur snygg Pythonkod kan vara. Trac är för övrigt en annan sak jag gillar.)

Samtidigt anser jag mig fortfarande mycket av en Python-novis. Jag använder få av språkets många funktioner, men det är inget problem utan med de kunskaper jag har i dag kan jag snabbt och enkelt göra det jag vill. Sedan är det bara kul att lära sig nya aspekter av språket som gör mig än mer effektiv.

I morse satte jag mig ned och testade generatorer (generators), dvs funktioner som kan fungera som en tillståndsmaskin, eller varför inte som uppdateringsfunktionen i ett strömkrypto.

När jag ändå är igång och erkänner en massa saker kan jag väl erkänna att jag gillar strömkryptot RC4. Ja, det har sina vårtor, speciellt i vissa tillämpningar. Men jag vet få relativt bra krypton som är så enkla att förstå och där man lätt kommer ihåg algoritmen som RC4 (försök att memorera AES-algoritmen).

En annan fördel med RC4 är att RC4 går att köra för hand med papper och penna om så krävs. Och med en nyckel som skalar till 4096 bitar, om man tar hänsyn till FMS-attacken (och kastar bort säg 4096 bytes från strömmen) är det fortfarande ett rätt säkert krypto.

Därför valde jag i morse att implementera RC4 som en Pythongenerator. Själva generatordelen av koden ser ut så här:


def rc4(key):

# RC4 stream generation. The while loop will yield between # function calls and return the latest key stream value. ipoint = 0 jpoint = 0 while(True): ipoint = (ipoint + 1) % 256 idata = state_array[ipoint] jpoint = (jpoint + idata) % 256 jdata = state_array[jpoint] state_array[ipoint] = jdata state_array[jpoint] = idata kpoint = (idata + jdata) % 256 kdata = state_array[kpoint] yield(kdata)

(Ja, koden går att dra ihop och bla går swap att göra på ett mer kompakt sätt…)

Notera satsen yield. Detta kommando beter sig som en vanlig return-sats, men skillnaden är att tillståndet hos funktionen bevaras, och vid nästa anrop fortsätter exekveringen efter yield-satsen, dvs nästa varv i while()-satsen.

För att använda en generator skapar man en referens till funktionen genom att göra en tilldelning. Men eftersom funktionen innehåller en yield-sats och därmed är en generator kommer Python att skapa ett objekt (allt i ett Pythonprogtam är ju objekt) med en next()-metod. Och det är via den vi sedan kör vår generator:

# Create an RC4 generator initialized with a key. my_key = “Kryptoblog” my_rc4 = rc4(my_key) # Generate a short key stream. print “RC4 key stream for key ‘%s’:” % my_key for i in range(16): print ” key stream value %d = %d” % (1, my_rc4.next())

När jag kör detta program får jag följande:


js@sotis:/Users/js/tmp/Div>./rc4_test.py
RC4 key stream for key ‘Kryptoblog’:

key stream value 0 = 184 key stream value 1 = 152 key stream value 2 = 122 key stream value 3 = 134 key stream value 4 = 184 key stream value 5 = 174 key stream value 6 = 24 key stream value 7 = 177 key stream value 8 = 238 key stream value 9 = 192 key stream value 10 = 172 key stream value 11 = 176 key stream value 12 = 86 key stream value 13 = 90 key stream value 14 = 51 key stream value 15 = 205

Det som inte finns med i koden ovan är initieringsdelen av RC4, vilket naturligtvis måste finnas med för att vi skall få ut en korrekt nyckelström. Jag kommer att lägga upp det kompletta programmet på en sida här på bloggen. Återkommer om detta.

Min erfarenhet av att leka en söndagsmorgon med Python-generatorer är att det fungerade precis som jag hoppats, att det var enkelt att använda och fungerade bra för att implementera en funktion som RC4.

(Vill man se en objektorienterad Pythonimplementation av RC4 i finns det en på Wikipedias sida för RC4, vilket jag upptäckte när jag byggt klart mitt hack och skulle äta frukost….)

No related posts.

Related posts brought to you by Yet Another Related Posts Plugin.

Advertisement

9 comments

  1. Martin says:

    Uerk! Jag har pulat lite med Python för att fixa några grejer till Mercurial och trots att jag jobbat med objektorienterade språk många år så kände jag aldrig att jag fick kläm på Python.

    Däremot gillar jag Ruby skarpt! Språken är inte så väldigt olika, men av någon anledning passade Ruby mig bättre!?

    Jag kan inte sätta fingret på varför det var lättare att lära sig det, men kanske berodde det på att jag hade en kompis att vända mig till med alla mina Ruby frågor. Får nog blogga lite om det 🙂

  2. Daniel N says:

    Kul att höra fler som fallit för samma saker (Python och Trac)! 🙂

    Har följt din blogg länge då du har många intressanta poster om säkerhet på alla nivåer, och att du nu kommer med Pythonkod som exempel gör inte saken sämre.

    Ser redan fram emot nästa postning!

  3. Martin M says:

    Kul exempel!

    De flesta python-programmerare skulle nog dra ihop swap-raderna till en enda och skriva “while True” istället för “while(True)”. Jag håller med den andra Martin om att Ruby har sina goda sidor – men själv tycker jag att python-kod har en tendens att bli enhetligare och lättare att läsa. Jag måste dock medge att exempelvis @ är snyggare än “self.” och att funktioner som returnerar booleska värden slutar på ? är en god idé. Loop- och iteratorsyntaxen i python utläses mer likt naturligt språk, medan delarna i ruby hamnar i en konstig ordning på grund av likheten med funktionsanropssyntax. På det hela taget så är enhetligheten i kodningsstil (vilket gör koden lättläst) och det stora antalet bra bibliotek de främsta anledningarna till att jag föredrar python.

  4. Joachim says:

    Aloha!

    Martin, japp håller med om swap-satsen och har faktiskt ändrat koden till att köra:

    i,j = j, i

    Vad gäller While(True) är det en av de mycket få saker jag inte håller med vad som är kutym i Pythovärlden. Jag vill se markera uttrycket som utvärderas. Notera att PEP8 inte säger något om just detta (vad jag kan se).

    PEP:arna gillar jag för övrigt. Ovanligt att det finns så många och tydliga förklaringar och motiveringar till varför språket ser ut som det gör, hur språket utvecklas och varför man rekommenderar att göra en viss sak.

    En sak du kanske kan berätta är vad som händer om jag skapar en klass där en metod avslutas med yield och därmed blir en generator. Får man ett separat objekt av metoden? Har inte testat detta än… 😉

    Kul att så många här tyckte om mitt hack.

  5. Joachim says:

    Aloha!

    Gjorde ett snabbtest att skapa en klass med en metod som är en generator. Försökte sedan anropa denna och får lite fina fel:

    TypeError: int argument required
    TypeError: int() argument must be a string or a number, not ‘generator’

  6. RodrigoH says:

    Tjena!

    Ännu en Python fantast här!, iofs rätt nyligen men jag tycker att språket gick snabbt att sätta sig in i.

    Förresten så har google också förstått värdet av python 🙂
    http://www.idg.se/2.1085/1.154794

  7. Martin M says:

    Joachim:
    Nej, PEP8 säger inget om parenteser runt while-vilkoret, men jag kan inte se varför parenteser på något vis skulle göra uttrycket tydligare. Det är ju liksom en av idéerna med syntaxen – att inte använda för mycket specialtecken. Känns inte som något större stilbrott dock.

    Angående generatorerna – hur ser din metodsignatur ut? Om du vill använda några argument utöver self verkar det som om man måste ange default-värden för att det ska fungera. Av någon anledning verkar antal “positional arguments” vara begränsat till ett. Exempel:

    class Test:
    def iterator(self, n=10):
    for i in range(n):
    ____yield i

    test = Test()
    for x in test.iterator(5):
    print x

  8. Joachim says:

    Aloha!

    Martin: Jag tycker att det blir tydligare att stänga inne expressions så att man det blir tydligt vad som skall utvärderas och leverera True/False. Som ett funktionsanrop. Parenteserna är en bra syntaktisk avgränsning.

    Intressant det du skriver om att man måste skicka med defaultvärden och positional. Får testa själv. Tack för att du tog dig tid att koda ihop det.

Leave a Reply

You must be logged in to post a comment.