Sfida di coding a Graz: E il vincitore è..
In occasione dei Graz Linux Days, grommunio ha ospitato una sfida di coding molto apprezzata. Dei 23 partecipanti, 9 sono stati in grado di presentare risultati di successo. Il vincitore del primo premio, estratto a sorte, ha ritirato il premio presso l’ufficio di grommunio.
In effetti sembra piuttosto semplice, non è vero?
“Per questo compito, è necessario scrivere codice C/C++ nel file \src\main.cpp per risolvere la sfida di codifica alla fine di questo file Readme. Viene utilizzato MinGW64 con gcc/g++ 15.2, che viene impostato automaticamente in una directory locale e può essere utilizzato con i seguenti comandi. ”
Ciò che potrebbe sembrare incomprensibile a molte persone non tecniche non sembra difficile ai programmatori, almeno a prima vista. In linea di principio, i quattro compiti che grommunio aveva incluso erano certamente risolvibili, e così 23 esperti di Linux hanno accettato la sfida un sabato di aprile a Graz.
Programmazione sotto pressione
Molti partecipanti hanno lottato contro il limite di tempo entro il quale dovevano trovare la soluzione corretta utilizzando il codice che avevano scritto loro stessi. La stima iniziale di 20 minuti si è rivelata troppo ottimistica; anche nei 40 minuti finali assegnati, solo 9 partecipanti sono riusciti a trovare la soluzione corretta.
Di conseguenza, le due macchine Windows appositamente preparate a Graz sono state occupate quasi ininterrottamente il sabato, con più di sette ore dedicate alla sfida stessa.
Il setup della sfida di coding
i dipendenti di grommunio hanno creato nuovi account utente sui computer, hanno impostato VSCode come editor e hanno automatizzato vari comandi tramite script cmd di Windows per accelerare il processo di compilazione e invio.
“Abbiamo creato un piccolo endpoint HTTP che, in combinazione con uno script di shell sui computer della sfida, ci ha permesso di generare input personalizzati per ogni partecipante in base al suo indirizzo e-mail e di rispondere con un feedback sui suoi tentativi di risolvere il problema ”, spiega Fabian Ortner di grommunio (nella foto sopra). “Un file Readme forniva poi una descrizione più dettagliata di ciò che era necessario fare per il compito di programmazione, e così è stato creato un processo abbastanza semplice e automatizzato per rendere la partecipazione il più facile possibile ”
Ma la parte “più semplice possibile” non è durata a lungo. Per la sfida, i partecipanti dovevano riparare un server di posta malfunzionante scrivendo un piccolo script di conversione. Nel README, il primo dei quattro compiti da risolvere inizia con:
“Sembra che ogni riga contenga un multiplo intero di 8 caratteri, quindi cerchiamo di interpretarli come singoli byte. Per esempio:
010001000101000101001010 0x44 0x51 0x4A
010001000101000001001100 => 0x44 0x50 0x4C
010000100101000101001100 0x42 0x51 0x4C
Sappiamo che il vecchio server di posta utilizzava un metodo di crittografia molto semplice dopo l’esportazione dell’email:
- Prendere ogni riga di testo, cioè ogni byte
- Per ogni riga, eseguire una crittografia XOR con la chiave ´grommunio´, carattere per carattere
- *Se una riga è più lunga della chiave, applicare di nuovo la chiave, iniziando dal primo carattere”
Seguirono altri requisiti e compiti che fecero davvero girare la testa. Solo pochi partecipanti sono riusciti a trovare le soluzioni corrette.
Ma anche chi non ce l’ha fatta ha avuto di che gioire: alla fine, un’estrazione casuale tra tutti i partecipanti ha stabilito chi avrebbe ricevuto la PlayStation promessa. Il vincitore Andreas è stato invitato a ritirarla al 30° piano della DC Tower di Vienna, nella sede di grommunio.
La soluzione? Non sarà pubblicata qui, ma il file README con la descrizione completa del problema è disponibile sotto questo post. Senza il server costruito da grommunio per i Graz Linux Days, tuttavia, ci vorrà un po’ di immaginazione..
Per saperne di più su grommunio ai Graz Linux Days, consultare questo articolo.
Istruzioni per la sfida di codifica
Questa sfida richiede di scrivere del codice C/C++ all’interno di .\src\main.cpp per risolvere la sfida alla fine di questo file. Utilizza MinGW64 con gcc/g++ 15.2 che viene impostato automaticamente in una directory locale e può essere usato con i seguenti comandi.
Ci sono quattro comandi importanti per lo script incluso:
1. Per registrare il proprio indirizzo e-mail e avviare il timer di 20 minuti:
`.´glt.cmd start“
2. Per costruire il codice:
.´glt.cmd build
3. Per compilare ed eseguire il codice e stamparne l’output nel terminale:
`.´glt.cmd build_and_run“
4. Per costruire, eseguire e inviare la soluzione:
.\glt.cmd submit
Il comando usato per costruire la soluzione non ha ottimizzazioni abilitate per impostazione predefinita:
g++.exe -static -O0 -g -std=c++17 src\main.cpp -o build/app.exe
Sfida
Per iniziare la sfida, prima inserite il vostro indirizzo e-mail nel file user.txt e poi usate il comando start per ottenere il vostro input. Lo usiamo solo per contattarvi nel caso in cui vinciate l’estrazione. È sufficiente modificare la variabile risultato nel codice e poi eseguire il comando di invio per verificare se è corretto.
WOW. Cosa è successo a quell’e-mail durante la migrazione? In qualche modo uno dei vostri messaggi di posta elettronica si è corrotto durante la configurazione del nuovo server di posta. Sembra che consista solo di simboli binari divisi in poche righe (il vostro input). Sembra che ci sia un multiplo intero di 8 simboli per riga, quindi proviamo a interpretarli come singoli byte. Per esempio:
010001000101000101001010 0x44 0x51 0x4A
010001000101000001001100 => 0x44 0x50 0x4C
010000100101000101001100 0x42 0x51 0x4C
Sappiamo che il vecchio server di posta utilizzava una crittografia molto semplice dopo l’esportazione delle e-mail:
- Prendere ogni riga di testo, cioè ogni byte
- XOR ogni riga con la chiave grommunio per carattere
- Se una riga è più lunga della chiave, è sufficiente riutilizzare la chiave a partire dal primo carattere.
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
Sembra già più promettente, ma ci sono ancora molti caratteri incasinati..
In passato il vecchio mailserver aveva già problemi con gli offset sui valori dei singoli caratteri, con l’offset che dipendeva da due cose:
- Un ** checksum orizzontale** dell’indirizzo e-mail
- l’indice del carattere in una riga e il numero di riga in cui si trova
All’epoca, il server calcolava un checksum orizzontale, semplicemente sommando tutti i byte dell’indirizzo e-mail.
[email protected] => (m=109) + (a=97) + (x=120) + ... = 2888
Quindi, per ogni carattere, è stato calcolato il suo spostamento positivo prendendo il checksum modulo della sua posizione nella riga. Per correggere questo errore dobbiamo quindi sottrarre i valori di offset da ogni byte. Inoltre, questi offset vengono spostati a sinistra di un carattere dopo ogni riga.
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) = '#'
Ora questo sembra un messaggio corretto! Ma per assicurarci di avere un algoritmo corretto, dobbiamo calcolare il prodotto elementare dei valori di offset per i valori dei caratteri di ogni carattere chiave utilizzato e sommarli per ogni carattere #`` nel messaggio. (\ne\r` dovrebbero essere scartati)
(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
È necessario scrivere questa somma di prodotti elementari nella variabile risultato per terminare la sfida di codifica!