Min nya hobby att implementera krypton i programspråket Python har den senaste veckan gjort att jag pillat med kryptot Snow.
Snow är ett strömkrypto av Thomas Johansson och Patrik Ekdahl vid LTH. Den version av Snow jag implementerat är Snow 2.0 som kom 2002. Snow 2.0 var en av kandidaterna till NESSIE-projektet och har även använts som jämförelse med kandidater i eSTREAM.
Det finns en nyare version av Snow kallad Snow 3G. Snow 3G är det krypto som används som bas i algoritmerna EUA2 och EIA2 för att säkra kommunikationen i 3G. Jag har ännu inte lagt in stöd för Snow 3G. En sÃ¥dan förändring skulle dock vara relativt enkel – det som krävs är väsentligen att lägga till ett extra register i FSM:en.
Snow arbetar pÃ¥ 32-bitars ord och kryptot bestÃ¥r i grunden av ett skiftregister (en LFSR-kedja) med 16 steg samt en tillstÃ¥ndsmaskin (FSM) med tvÃ¥ 32 tillstÃ¥ndsregister – R1 och R2.
Uppdateringen av LFSR-kedjan sker genom återmatning av tidigare värden som mixas samman genom två multiplikationer, vilka är implementerade med tabeller. Uppdateringen av R2-registret i FSM:en sker genom en S-box (baserad på S-boxen i AES) där indata är värdet i R1. Totalt sett finns det sex stycken tabeller i den här implementationen av Snow.
Min implementation av Python är en fristående klass med metod load_key() för att ladda nyckel och IV, samt en metod gen_keyword() för att generera nästa nyckelströmsord. Klassen stödjer både 128- och 256-bitars nyckel.
LFSR-kedjan och FSM:en är sammankopplade på ett relativt intrikat sätt och att få ordning på ordningen i uppdateringen i ett sekventiellt program visade sig vara lite klurigt. Men genom att dumpa alla interna tillstånd gick det att få ordning på sekvenserna. Min implementation av Snow inkluderar därför en metod för att dumpa interntillståndet. När ett objekt av Snow skapas går det även att ange hur pratig (verbose) den skall vara när den utför en metod.
Ett litet exempel (hämtat från exempelkoden):
my_snow = Snow(False) my_key = [0×00000000, 0×00000000, 0×00000000, 0×80000000] my_iv = [0×00000000, 0×00000000, 0×00000000, 0×00000000] my_snow.load_key(my_key, my_iv) my_snow.gen_keyword()
Detta ger (med lite utskrifter och en loop):
key:
[0, 0, 0, 2147483648L]
iv:
[0, 0, 0, 0]
running key 0: 8d590ae9
running key 1: a74a7d05
running key 2: 6dc9ca74
running key 3: b72d1a45
running key 4: 99b0a083
running key 5: fb45d13f
running key 6: cf9411bd
running key 7: 9a503783
running key 8: a98265ae
running key 9: bf2dc77f
running key 10: f2eb41e4
running key 11: aa896508
running key 12: 19d8ab8f
running key 13: 2eb8077f
running key 14: 78f8c1f1
running key 15: 9d4c5ce2
Rent och snyggt gränssnitt om jag får säga det själv, HW-nisse som jag är (så vad vet jag?).
Jag har testkört på min laptop med 2GHz Core 2 Duo-processor. Generering av 10.000.000 värden tar 135 sekunder, vilket ger ungefär 295 kByte/s. Inte kanonsnabbt, men vill man ha en ren Pythonimplementation av en applikation där det finns ett behov av att skydda data med hjälp av ett bra krypto kanske den här implementationen kan vara användbar.
Min implementation av Snow finns på sidan för nedladdning. Det finns ett par korta exempel i main()funktionen med testvektorer för 128 och 256-bit nycklar hämtade från specifikationen för Snow 2.0.
Koden är BSD-licensierad och jag hoppas att den kommer till nytta. Mycket nöje!