Coding Challenge i Graz: Og vinneren er..
På Linux-dagene i Graz arrangerte grommunio en svært anerkjent kodeutfordring. Av de 23 deltakerne var det 9 som kunne presentere vellykkede resultater. Hovedvinneren, som ble trukket ut ved loddtrekning, har nå hentet premien sin på grommunio-kontoret.
Det høres egentlig ganske enkelt ut, ikke sant?
“For denne oppgaven må du skrive C/C++-kode i filen \src\main.cpp for å løse kodingsutfordringen på slutten av denne Readme-filen. MinGW64 med gcc/g++ 15.2 brukes, som automatisk settes opp i en lokal katalog og kan brukes med følgende kommandoer.”
Det som kan høres uforståelig ut for mange ikke-tekniske mennesker, virker ikke vanskelig for programmerere - i hvert fall ikke ved første øyekast. I prinsippet var de fire oppgavene grommunio hadde satt opp, absolutt løsbare, og 23 Linux-eksperter tok utfordringen en lørdag i april i Graz.
Programmering under tidspress
Mange av deltakerne slet med tidsbegrensningen de hadde på seg til å finne den riktige løsningen ved hjelp av egenskrevet kode. Det opprinnelige estimatet på 20 minutter viste seg å være altfor optimistisk; selv innenfor de 40 minuttene som var satt av, var det bare 9 deltakere som klarte å finne korrekte løsninger.
Resultatet var at de to spesialtilpassede Windows-maskinene i Graz var i bruk nesten hele lørdagen, og mer enn sju timer var avsatt til selve utfordringen.
Oppsettet for Coding Challenge
grommunio-ansatte hadde opprettet nye brukerkontoer på datamaskinene, satt opp VSCode som editor og automatisert ulike kommandoer via Windows cmd-skript for å få fart på kompilerings- og innsendingsprosessen.
*“Vi satte opp et lite HTTP-endepunkt som, i kombinasjon med et skallskript på utfordringsdatamaskinene, gjorde det mulig for oss å generere personlig tilpasset input for hver deltaker basert på e-postadressen deres, og deretter svare med tilbakemeldinger på forsøkene deres på å løse problemet”, forklarer Fabian Ortner fra grommunio (bildet over). “En Readme-fil ga en mer detaljert beskrivelse av hva som måtte gjøres for å løse programmeringsoppgaven, og på den måten ble det skapt en ganske enkel, automatisert prosess for å gjøre deltakelsen så enkel som mulig.”
Men “så enkelt som mulig”-delen varte ikke lenge. I utfordringen skulle deltakerne fikse en e-postserver som ikke fungerte som den skulle ved å skrive et lite konverteringsskript. I README begynner den første av fire oppgaver som skal løses med
“Det ser ut til at hver linje inneholder et heltallsmultiplum av 8 tegn, så la oss prøve å tolke disse som individuelle byte. For eksempel:
010001000101000101001010 0x44 0x51 0x4A
010001000101000001001100 => 0x44 0x50 0x4C
010000100101000101001100 0x42 0x51 0x4C
Vi vet at den gamle e-postserveren brukte en veldig enkel krypteringsmetode etter eksport av e-posten:
- Ta hver tekstlinje, dvs. hver byte
- For hver linje, utfør en XOR-kryptering med nøkkelen “grommunio”, tegn for tegn
- *Hvis en linje er lengre enn nøkkelen, anvender du bare nøkkelen på nytt, og begynner med det første tegnet.”
Deretter fulgte flere krav og oppgaver som virkelig fikk hodene deres til å snurre. Bare noen få deltakere klarte å komme opp med de riktige løsningene.
Men selv de som ikke lyktes, hadde noe å se frem til: Til slutt avgjorde en tilfeldig trekning blant alle deltakerne hvem som skulle få den lovede PlayStation-en. Vinneren Andreas ble invitert til å hente den i 30. etasje i DC Tower i Wien, i grommunios hovedkvarter.
Løsningen? Den vil ikke bli lagt ut her, men README-filen med hele problemstillingen er tilgjengelig under dette innlegget. Uten serveren som grommunio bygde for Graz Linux Days, vil det imidlertid kreve litt fantasi..
Les mer om grommunio på Graz Linux Days i denne artikkelen.
Instruksjoner for kodingsutfordringen
Denne utfordringen krever at du skriver litt C/C++-kode i .\src\main.cpp for å løse utfordringen på slutten av dette readme. Den bruker MinGW64 med gcc/g++ 15.2, som settes opp automatisk i en lokal katalog og kan brukes med følgende kommandoer.
Det er fire viktige kommandoer for det inkluderte skriptet:
1. For å registrere e-postadressen din og starte 20min timeren:
.\glt.cmd start
2. For å bare bygge koden din:
.\glt.cmd build
3. For å bygge og kjøre koden din og skrive ut utdataene til terminalen:
.\glt.cmd build_and_run
4. For å bygge, kjøre og sende inn løsningen:
.\glt.cmd submit
Kommandoen som brukes til å bygge løsningen din, har ingen optimaliseringer aktivert som standard:
g++.exe -static -O0 -g -std=c++17 src\main.cpp -o build/app.exe
Utfordring
For å starte utfordringen, først legg inn e-postadressen din i filen user.txt og bruk deretter start-kommandoen for å få innspillene dine. Vi bruker den bare, for å kontakte deg i tilfelle du vinner tegningen. Du trenger bare å endre result-variabelen i koden din og deretter kjøre submit-kommandoen for å sjekke om den er riktig.
WOW. Hva skjedde med den e-posten under migreringen? På en eller annen måte ble en av e-postene dine ødelagt under installasjonen av den nye e-postserveren. Den ser ut til å bestå av binære symboler fordelt på noen få linjer (inndataene dine). Det ser ut til å være et heltallsmultiplum av 8 symboler per linje, så la oss prøve å tolke dem som individuelle byte. For eksempel
010001000101000101001010 0x44 0x51 0x4A
010001000101000001001100 => 0x44 0x50 0x4C
010000100101000101001100 0x42 0x51 0x4C
Vi vet at den gamle e-postserveren brukte en veldig enkel kryptering etter å ha eksportert e-posten:
- Ta hver tekstlinje, dvs. hver byte
- XOR hver linje med nøkkelen grommunio tegnvis
- Hvis en linje er lengre enn nøkkelen, er det bare å gjenbruke nøkkelen fra og med det første tegnet.
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 mer lovende ut allerede, men fortsatt er det mange tegn som ikke stemmer..
Den gamle mailserveren hadde allerede i tidligere tider problemer med forskyvninger på individuelle tegnverdier, der forskyvningen var avhengig av to ting:
- En horisontal kontrollsum av e-postadressen din
- indeksen til tegnet i en linje og linjenummeret det står i
På den tiden beregnet serveren en horisontal kontrollsum ved ganske enkelt å legge sammen alle byteverdiene i e-postadressen din.
[email protected] => (m=109) + (a=97) + (x=120) + ... = 2888
For hvert tegn ble den positive forskyvningen beregnet ved å ta sjekksummen modulert med tegnets posisjon i linjen. For å rette opp denne feilen må vi derfor trekke fra offsetverdiene fra hver av bytene. I tillegg forskyves disse offsetverdiene til venstre med ett tegn etter hver linje.
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) = '#'
Nå ser dette ut som en korrekt melding! Men for å sikre at vi har en korrekt algoritme, må vi beregne det elementvise produktet av offsetverdiene ganger tegnverdiene for hvert nøkkeltegn som er brukt, og summere dem for hvert #-tegn i meldingen. (\n og \r skal forkastes)
(g=103)*0 + (r=114)*0 + (o=111)*2
+ (g=103)*0 + (o=111)*0
+ (g=103)*2 + (r=114)*0 + (o=111)*0 = 428
Du må skrive denne summen av elementvise produkter til resultatvariabelen for å fullføre kodingsutfordringen!