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….)