Hoppa till innehåll
Blog

Kodningsutmaning i Graz: Och vinnaren är..

· av grommunio
Kodningsutmaning i Graz: Och vinnaren är..

På Linuxdagarna i Graz anordnade grommunio en mycket uppskattad kodningsutmaning. Av de 23 deltagarna kunde 9 presentera framgångsrika resultat. Vinnaren av huvudpriset, som utsågs genom lottning, har nu hämtat sitt pris på grommunios kontor.

Kodningsutmaning - vinnare
Fabian Ortner från grommunio överlämnar en helt ny Sony PlayStation 5, värd nästan 700 euro, till den lyckliga vinnaren Andreas.

Det låter faktiskt ganska enkelt, eller hur?

“För den här uppgiften måste du skriva C/C++-kod i filen \src\main.cpp för att lösa kodningsutmaningen i slutet av den här Readme-filen. MinGW64 med gcc/g++ 15.2 används, som automatiskt konfigureras i en lokal katalog och kan användas med följande kommandon.”

Det som kan låta obegripligt för många icke-tekniska personer verkar inte svårt för programmerare - åtminstone inte vid första anblicken. I princip var de fyra uppgifter som grommunio hade inkluderat säkert lösbara, och därför tog 23 Linux-experter sig an utmaningen en lördag i april i Graz.

Programmering under tidspress

Många deltagare kämpade med tidsgränsen inom vilken de var tvungna att hitta rätt lösning med hjälp av kod som de själva hade skrivit. Den ursprungliga uppskattningen på 20 minuter visade sig vara alldeles för optimistisk; även under de sista 40 minuterna var det bara 9 deltagare som lyckades hitta korrekta lösningar.

Som ett resultat av detta var de två speciellt förberedda Windows-maskinerna i Graz upptagna nästan oavbrutet under lördagen, med mer än sju timmar avsatta för själva utmaningen.

Upplägget för kodningsutmaningen

grommunios medarbetare hade skapat nya användarkonton på datorerna, installerat VSCode som editor och automatiserat olika kommandon via Windows cmd-skript för att påskynda sammanställnings- och inlämningsprocessen.

Kodningsutmaning - kod
En deltagare som framgångsrikt slutför utmaningen med de verktyg som tillhandahålls av grommunio.

*“Vi satte upp en liten HTTP-slutpunkt som, i kombination med ett skalskript på utmaningsdatorerna, gjorde det möjligt för oss att generera personlig inmatning för varje deltagare baserat på deras e-postadress och sedan svara med feedback på deras försök att lösa problemet”, förklarar Fabian Ortner från grommunio (bilden ovan). “En Readme-fil gav sedan en mer detaljerad beskrivning av vad som behövde göras för programmeringsuppgiften, och på så sätt skapades en ganska enkel, automatiserad process för att göra deltagandet så enkelt som möjligt.”

Men “så enkelt som möjligt”-delen varade inte länge. Utmaningen gick ut på att deltagarna skulle fixa en krånglande e-postserver genom att skriva ett litet konverteringsskript. I README börjar den första av fyra uppgifter som ska lösas med:

“Det verkar som om varje rad innehåller en heltalsmultipel av 8 tecken, så låt oss försöka tolka dessa som enskilda bytes. Till exempel:

010001000101000101001010 0x44 0x51 0x4A
010001000101000001001100 => 0x44 0x50 0x4C
010000100101000101001100 0x42 0x51 0x4C

Vi vet att den gamla e-postservern använde en mycket enkel krypteringsmetod efter att ha exporterat e-postmeddelandet:

  • Ta varje rad med text, dvs varje byte
  • För varje rad, utför en XOR-kryptering med nyckeln “grommunio”, tecken för tecken
  • Om en rad är längre än nyckeln, använd helt enkelt nyckeln igen, med början med det första tecknet.”

Fler krav och uppgifter följde som verkligen fick deras huvuden att snurra. Endast ett fåtal deltagare lyckades komma fram till de rätta lösningarna.

Men även de som inte lyckades hade något att se fram emot: i slutändan avgjordes vem som skulle få den utlovade PlayStation genom en slumpmässig dragning bland alla deltagare. Vinnaren Andreas blev inbjuden att hämta den på 30:e våningen i DC Tower i Wien, på grommunios huvudkontor.

Lösningen på problemet? Den kommer inte att publiceras här, men README-filen med hela problemformuleringen finns tillgänglig under det här inlägget. Utan den server som grommunio byggde för Graz Linux Days krävs det dock lite fantasi..

Läs mer om grommunio på Graz Linux Days i den här artikeln.


Instruktioner för kodningsutmaning

Den här utmaningen kräver att du skriver lite C/C++-kod inuti .\src\main.cpp för att lösa utmaningen i slutet av detta readme. Den använder MinGW64 med gcc/g++ 15.2 som konfigureras automatiskt i en lokal katalog och kan användas med följande kommandon.

Det finns fyra viktiga kommandon för det medföljande skriptet:

1. För att registrera din e-postadress och starta 20-minuterstimern:

.\glt.cmd start

2. För att bara bygga din kod:

.\glt.cmd build

3. För att bygga och köra din kod och skriva ut utdata till terminalen:

.\glt.cmd build_and_run

4. Så här bygger, kör och skickar du in din lösning:

.\glt.cmd submit

Det kommando som används för att bygga din lösning har inga optimeringar aktiverade som standard:

g++.exe -static -O0 -g -std=c++17 src\main.cpp -o build/app.exe

Utmaning

För att starta utmaningen ska du först skriva in din e-postadress i filen user.txt och sedan använda kommandot start för att få din input. Vi använder den bara för att kontakta dig om du vinner dragningen. Du behöver bara ändra variabeln result i din kod och sedan köra kommandot submit för att kontrollera om det är korrekt.

WOW. Vad hände med det där e-postmeddelandet under migreringen? På något sätt blev ett av dina e-postmeddelanden skadat under installationen av din nya e-postserver. Det verkar bara bestå av binära symboler uppdelade på några få rader (din inmatning). Det verkar finnas en heltalsmultipel av 8 symboler per rad, så låt oss försöka tolka dem som enskilda bytes. Till exempel

010001000101000101001010 0x44 0x51 0x4A
010001000101000001001100 => 0x44 0x50 0x4C
010000100101000101001100 0x42 0x51 0x4C

Vi vet att den gamla e-postservern använde en mycket enkel kryptering efter att ha exporterat e-postmeddelandet:

  • Ta varje textrad, dvs. varje byte
  • XOR varje rad med nyckeln grommunio karaktärsmässigt
  • Om en rad är längre än nyckeln återanvänder du helt enkelt nyckeln från och med det första tecknet.
0x44 ^ g = 0x23 0x51 ^ r = 0x23 0x4A ^ o = 0x25
0x44 ^ g = 0x23 0x50 ^ r = 0x22 0x4C ^ o = 0x23
0x42 ^ g = 0x25 0x51 ^ r = 0x23 0x4C ^ o = 0x23

Det ser redan mer lovande ut, men det finns fortfarande många röriga tecken ..

Förr i tiden hade den gamla mailservern redan problem med offsets på enskilda teckenvärden, där offseten berodde på två saker:

  • En horisontell kontrollsumma av din e-postadress
  • teckenets index på en rad och det radnummer det finns på

På den tiden beräknade servern en horisontell kontrollsumma genom att helt enkelt lägga ihop alla bytevärden i din e-postadress.

[email protected] => (m=109) + (a=97) + (x=120) + ... = 2888

För varje tecken beräknades sedan dess positiva offset genom att ta checksumman modulo dess position i raden. För att korrigera detta fel måste vi därför subtrahera offsetvärdena från var och en av byte. Dessutom förskjuts dessa offsets sedan åt vänster med ett tecken efter varje rad.

0x23 - (2888 % 1) = '#' 0x23 - (2888 % 2) = '#' 0x25 - (2888 % 3) = '#'
0x23 - (2888 % 2) = '#' 0x22 - (2888 % 3) = ' ' 0x25 - (2888 % 1) = '#'
0x23 - (2888 % 3) = '#' 0x23 - (2888 % 1) = '#' 0x25 - (2888 % 2) = '#'

Nu ser detta ut som ett korrekt meddelande! Men för att säkerställa att vi har en korrekt algoritm måste vi beräkna den elementvisa produkten av offsetvärdena gånger teckenvärdena för varje använt nyckeltecken och summera dem för varje #-tecken i meddelandet. (\n\ och \r\ bör kasseras)

    (g=103)*0 + (r=114)*0 + (o=111)*2
+ (g=103)*0 + (o=111)*0
(g=103)*0 + (r=114)*0 + (o=111)*0 + (g=103)*0 + (o=111)*0 = 428

Du måste skriva denna summa av elementvisa produkter till resultatvariabeln för att avsluta kodningsutmaningen!

Lycka till!