Przejdź do treści
Blog

Coding Challenge w Grazu: Zwycięzcą został..

· przez grommunio
Coding Challenge w Grazu: Zwycięzcą został..

Podczas Graz Linux Days, grommunio było gospodarzem cieszącego się dużym uznaniem wyzwania kodowania. Spośród 23 uczestników, 9 było w stanie zaprezentować udane wyniki. Zwycięzca nagrody głównej, wyłoniony w drodze losowania, odebrał już swoją nagrodę w biurze grommunio.

Coding Challenge - zwycięzca

Fabian Ortner z grommunio prezentuje nowiutką konsolę Sony PlayStation 5, wartą prawie 700 euro, szczęśliwemu zwycięzcy Andreasowi.

Brzmi to całkiem prosto, prawda?

“W tym zadaniu musisz napisać kod C/C++ w pliku \src\main.cpp, aby rozwiązać wyzwanie kodowania na końcu tego pliku Readme. Używany jest MinGW64 z gcc/g++ 15.2, który jest automatycznie konfigurowany w lokalnym katalogu i może być używany z następującymi poleceniami. ”

To, co może brzmieć niezrozumiale dla wielu nietechnicznych osób, nie wydaje się trudne dla programistów - przynajmniej na pierwszy rzut oka. Zasadniczo, cztery zadania zawarte w grommunio były z pewnością możliwe do rozwiązania, więc 23 ekspertów Linuksa podjęło wyzwanie w pewną kwietniową sobotę w Grazu.

Programowanie pod presją czasu

Wielu uczestników zmagało się z limitem czasu, w którym musieli znaleźć prawidłowe rozwiązanie przy użyciu kodu, który sami napisali. Początkowe oszacowanie 20 minut okazało się zbyt optymistyczne; nawet w ciągu ostatnich 40 minut tylko 9 uczestników było w stanie znaleźć prawidłowe rozwiązania.

W rezultacie dwa specjalnie przygotowane komputery z systemem Windows w Grazu były zajęte niemal bez przerwy w sobotę, z ponad siedmioma godzinami przeznaczonymi na samo wyzwanie.

Konfiguracja Coding Challenge

pracownicy grommunio utworzyli nowe konta użytkowników na komputerach, skonfigurowali VSCode jako edytor i zautomatyzowali różne polecenia za pomocą skryptów cmd systemu Windows, aby przyspieszyć proces kompilacji i przesyłania.

Coding Challenge - kod

Uczestnik, który pomyślnie ukończył wyzwanie za pomocą narzędzi dostarczonych przez grommunio.

“Skonfigurowaliśmy mały punkt końcowy HTTP, który w połączeniu ze skryptem powłoki na komputerach biorących udział w wyzwaniu, pozwolił nam wygenerować spersonalizowane dane wejściowe dla każdego uczestnika na podstawie jego adresu e-mail, a następnie odpowiedzieć z informacją zwrotną na temat jego prób rozwiązania problemu ” - wyjaśnia Fabian Ortner z grommunio (na zdjęciu powyżej). “Plik Readme zawierał następnie bardziej szczegółowy opis tego, co należy zrobić w celu wykonania zadania programistycznego, a zatem stworzono dość prosty, zautomatyzowany proces, aby maksymalnie ułatwić uczestnictwo. ”

Ale część “tak prosta, jak to tylko możliwe” nie trwała długo. W ramach wyzwania uczestnicy musieli naprawić nieprawidłowo działający serwer pocztowy, pisząc mały skrypt konwersji. W README, pierwsze z czterech zadań do rozwiązania zaczyna się od:

“Wygląda na to, że każda linia zawiera całkowitą wielokrotność 8 znaków, więc spróbujmy zinterpretować je jako pojedyncze bajty. Na przykład:

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

Wiemy, że stary serwer pocztowy używał bardzo prostej metody szyfrowania po wyeksportowaniu wiadomości e-mail:

  • Bierzemy każdy wiersz tekstu, czyli każdy bajt
  • Dla każdej linii wykonaj szyfrowanie XOR z kluczem `grommunio`, znak po znaku
  • *Jeśli linia jest dłuższa niż klucz, po prostu zastosuj klucz ponownie, zaczynając od pierwszego znaku”

Pojawiły się kolejne wymagania i zadania, od których naprawdę zakręciło się w głowie. Tylko nieliczni uczestnicy byli w stanie wymyślić poprawne rozwiązania.

Ale nawet ci, którym się nie udało, mieli na co czekać: w końcu losowanie wśród wszystkich uczestników zadecydowało o tym, kto otrzyma obiecane PlayStation. Zwycięzca Andreas został zaproszony do odebrania jej na 30. piętrze DC Tower w Wiedniu, w siedzibie grommunio.

Rozwiązanie? Nie zostanie ono tutaj opublikowane, ale plik README z pełnym opisem problemu jest dostępny pod tym postem. Jednak bez serwera zbudowanego przez grommunio na Graz Linux Days, będzie to wymagało trochę wyobraźni..

Dowiedz się więcej o grommunio na Graz Linux Days w tym artykule.


Coding Challenge Instructions

To wyzwanie wymaga napisania kodu C/C++ wewnątrz pliku .\src\main.cpp w celu rozwiązania zadania znajdującego się na końcu niniejszej instrukcji. Używa MinGW64 z gcc/g++ 15.2, który jest automatycznie konfigurowany w lokalnym katalogu i może być używany z następującymi poleceniami.

Istnieją cztery ważne polecenia dla dołączonego skryptu:

1. Aby zarejestrować swój adres e-mail i uruchomić 20-minutowy licznik czasu:

.\glt.cmd start

2. Aby po prostu zbudować swój kod:

.\glt.cmd build

3. Aby zbudować i uruchomić kod oraz wydrukować jego dane wyjściowe w terminalu:

.\glt.cmd build_and_run

4. Aby zbudować, uruchomić i przesłać rozwiązanie:

.\glt.cmd submit

Polecenie używane do kompilowania rozwiązania domyślnie nie ma włączonych optymalizacji:

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

Challenge

Aby rozpocząć wyzwanie, najpierw umieść swój adres e-mail w pliku user.txt, a następnie użyj komendy start, aby uzyskać swoje dane wejściowe. Używamy go tylko do kontaktu w przypadku wygrania losowania. Musisz tylko zmienić zmienną result w swoim kodzie, a następnie uruchomić polecenie submit, aby sprawdzić, czy jest poprawna.

WOW. Co się stało z tym e-mailem podczas migracji? W jakiś sposób jedna z wiadomości e-mail została uszkodzona podczas konfiguracji nowego serwera pocztowego. Wygląda na to, że składa się tylko z symboli binarnych podzielonych na kilka linii (dane wejściowe). Wydaje się, że w każdej linii znajduje się całkowita wielokrotność 8 symboli, więc spróbujmy zinterpretować je jako pojedyncze bajty. Na przykład:

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

Wiemy, że stary serwer pocztowy używał naprawdę prostego szyfrowania po wyeksportowaniu wiadomości e-mail:

  • Weź każdą linię tekstu, tj. każdy bajt
  • XOR każdej linii z kluczem grommunio po znakach
  • Jeśli linia jest dłuższa niż klucz, po prostu użyj klucza ponownie, zaczynając od pierwszego znaku.

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

Wygląda to już bardziej obiecująco, ale nadal jest wiele pomieszanych znaków..

W dawnych czasach stary serwer pocztowy miał już problemy z przesunięciami poszczególnych wartości znaków, przy czym przesunięcie zależało od dwóch rzeczy:

  • poziomej sumy kontrolnej adresu e-mail
  • indeksu znaku w linii i numeru linii, w której się znajduje

W tym czasie serwer obliczał poziomą sumę kontrolną, po prostu dodając do siebie wszystkie wartości bajtów adresu e-mail.

max.mustermann@grommunio.com => (m=109) + (a=97) + (x=120) + … = 2888

Następnie dla każdego znaku obliczono jego dodatnie przesunięcie, biorąc sumę kontrolną modulo jego pozycję w linii. Aby skorygować ten błąd, musimy zatem odjąć wartości przesunięcia od każdego z bajtów. Dodatkowo te przesunięcia są następnie przesuwane w lewo o jeden znak po każdej linii.

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) = ’#’

Teraz wygląda to na poprawną wiadomość! Ale aby upewnić się, że mamy poprawny algorytm, musimy obliczyć iloczyn pierwiastków wartości przesunięcia razy wartości znaków każdego użytego znaku klucza i zsumować je dla każdego znaku # w wiadomości. (\n i \r powinny zostać odrzucone)

(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

Aby ukończyć Wyzwanie Kodowania, należy zapisać tę sumę iloczynów mądrych pierwiastków w zmiennej wynikowej!

Powodzenia!