ilustracja rozkładu pseudolosowego
intel

Wylosuj czterocyfrową liczbę

Jeśli jesteś leniwy, to od razu Ci powiem: 4161. Jeśli chcesz się dowiedzieć, dlaczego akurat taka i jak od tej wiedzy zależy Twoje bezpieczeństwo – czytaj dalej.


Ważne na początek

To wpis eksperymentalny. Możesz to zauważyć choćby po nowej kategorii, która się pojawiła po prawej stronie.

Od pewnego czasu krążę wokół tematów, którymi wcześniej się nie zajmowałem: białego wywiadu, analityki i cyberbezpieczeństwa. Niektóre z nich traktuję hobbystycznie, inne wiążę z pracą, ale wszystkie trzy uważam za bardzo ważne umiejętności we współczesnym świecie. A ponieważ lubię dzielić się tym, co dla mnie ważne, chcę o nich czasem pisać na blogu.

Zacznę od wpisów popularno-naukowych, skierowanych głównie do czytelników stawiających pierwsze kroki w tych tematach. Mają być takie, żeby laik o podstawowych umiejętnościach obsługi komputera mógł je zrozumieć. Dla mnie będzie to sprawdzian, jak dobrze rozumiem dane zagadnienie. A jeśli pomysł się sprawdzi, z czasem poziom trudności poruszanych tematów zacznie rosnąć.

Pomimo takiej grupy docelowej, gorąco zachęcam czytelników bardziej doświadczonych do czytania i komentowania wpisów – śmiało możecie wytykać moje błędy i prostować je, żebym też mógł się czegoś nauczyć. Tak, jak kiedyś wyszło w przypadku wpisu o bezpieczeństwie haseł.

Przyszłość tej serii zależy od tego, jak Wam się spodoba, dlatego śmiało daj znać przez przyciski na dole albo komentarze, co myślisz o takim pomyśle. Możesz też pod wpisem zasugerować tematy, które powinienem poruszyć w przyszłości.

Dlaczego zawracam Ci tym głowę?

Liczby losowe to podstawa naszego codziennego bezpieczeństwa. Opierają się na nich algorytmy szyfrujące, logowanie wieloetapowe, czy choćby wybór osób do dokładnej kontroli albo overbookingu na lotniskach. Nie mówiąc już o tym, że wiele osób chce na nich zbudować bezpieczeństwo finansowe i uparcie wierzy, że przechytrzy maszynę losującą w kolekturze.

Jak się jednak okazuje, zorganizowanie losowania jest dość drogie. Można za to tanio wygenerować liczby które dla człowieka wyglądają na losowe, chociaż wcale takie nie są. Liczby te nazywają się „pseudolosowymi” i bardzo często są wykorzystywane w najróżniejszym oprogramowaniu. Żeby nie szukać daleko – dokładnie tego typu liczbę otrzymasz, jeśli w dowolnej komórce Excela wpiszesz

=los()

i naciśniesz enter (powinno też zadziałać na LibreOffice i w arkuszach Google).

W tym wpisie chcę Ci pokazać, jak są „losowane” takie liczby.

A właściwie, to po co mi to?

Być może nigdy nie będziesz musiał tworzyć takiego generatora albo próbować odgadnąć, jakim algorytmem wybierane są liczby. Ale skoro żyjesz w czasach, w których technologie cyfrowe są powszechne (a żyjesz, skoro to czytasz na blogu) warto żebyś wiedział, że nie wszystko jest tak losowe, jak się może wydawać. Jak to powiedział jedyny SEALs, którego spotkałem na żywo:

Nigdy nie wiesz, kiedy jakaś wiedza się przyda. Kiedyś na misji spotkaliśmy stado dzikich koni i udało nam się uniknąć wykrycia tylko dlatego, że jeden gość z sekcji kiedyś pracował w cyrku i wiedział, jak obchodzić się z dzikimi zwierzętami.

Tak więc zachęcam do pozostania na stronie nawet, jeśli nie lubisz matematyki.

Jak komputer „losuje” liczby?

Dlaczego we wstępie do wpisu pojawiło się 4161, a słowo „losowanie” w nagłówku sekcji umieściłem w cudzysłowie?

Jak wspomniałem, celem było wylosowanie liczby czterocyfrowej albo, jak kto woli, z zakresu od 0 do 9999 (1 można zawsze zapisać jako 0001). Żeby takową wygenerować „po komputerowemu”, potrzebujemy ziarna (ang. seed, czyli jakiejś liczby wyjściowej) i algorytmu do jego przetworzenia na coś w miarę losowego.

Zacząłem pisać ten wpis 2 września o godzinie 21:16 (teraz wyjdzie, ile mi zajmuje teraz tworzenie jednego wpisu, ale co tam). Wykorzystam to w przykładzie i oprę swoje ziarno o czas, a dokładniej o numer dnia, numer miesiąca, godzinę i liczbę minut. Moje pierwotne składowe to 02, 09, 21 i 16.

Teraz czas na algorytm przetwarzający ziarno w liczbę, która ma wyglądać na losową. Zanim zacznę wykonywać operacje matematyczne, zamienię miejscami cyfry w moim ziarnie – odwrócę te w numerze dnia i godziny. Będzie to pierwsza rzecz utrudniająca odgadnięcie mojego algorytmu, a przy okazji zapewni przez co najmniej 90% czasu (poza 10, 20 i 30 dniem miesiąca) ziarno rzędu dziesiątek milionów (co będzie nie bez znaczenia w użytym przeze mnie algorytmie). Po pierwszej operacji mam więc liczbę:

20091216

Teraz wykonam kolejne operacje, które pozwolą mi otrzymać docelową liczbę. Mój algorytm obliczeniowy obejmuje pięć kroków:

  1. zmienię kolejność cyfr w ziarnie, jak opisałem powyżej,
  2. podniosę otrzymaną liczbę do kwadratu (dostanę 403656960358656),
  3. z wyniku spiszę liczby od trzeciej do szóstej licząc od końca (dostanę 6853),
  4. otrzymaną liczbę podniosę do potęgi trzeciej (dostanę 321841612477),
  5. z wyniku spiszę liczby od piątej do ósmej (dostanę 4161).

Dostałem dokładnie tę samą liczbę, którą podałem Ci we wstępie do wpisu jako losową.

Niesamowite, prawda?

Taki generator liczb pseudolosowych możesz w prosty sposób napisać w Excelu. Możesz też zaimplementować go w Pythonie poniższym kodem (do uruchomienia możesz wykorzystać np. Google Colab):

def generate_pseudonumber(day, month, hour, minute):
  """Simple algorithm generating pesudonumbers"""
    seed = day[::-1] + month + hour[::-1] + minute
    return int(str(int(str(int(seed)**2)[-3:-7:-1])**3)[4:8])

Teraz możesz przetestować algorytm wykorzystując datę i godzinę, o której podałem wyżej (dostaniesz 4161):

generate_pseudonumber("02", "09", "21", "16")

albo zobaczyć co wyjdzie, jeśli wykorzystasz aktualny czas:

from datetime import datetime
generate_pseudonumber(datetime.now().strftime("%d"), datetime.now().strftime("%m"), datetime.now().strftime("%H"), datetime.now().strftime("%M"))

Jak widzisz, moja liczba losowa wcale nie jest losowa. Została otrzymana w bardzo konkretny i powtarzalny sposób.

Co dalej z taką „losowością”?

Jeśli zastosowałbym ten sam algorytm minutę później, dostałbym 625. Wychodząc z ziarna 20091217, w kroku drugim otrzymam 0145, co podniesione do potęgi trzeciej da 3048625 – więc z przewidzianych czterech cyfr dostałem tylko trzy. W sumie tylko ode mnie zależy, czy brakujące cyfry uzupełnię zerami na początku, czy na końcu ciągu, bylebym to robił konsekwentnie. Tak więc w tym algorytmie dopisuję 0 na początku liczby, jeśli jest to potrzebne.

Idąc dalej: jeśli zastosuję algorytm 2 września 2023 o 21:16, dostanę dokładnie taki sam wynik, jak we wstępie. Mój algorytm okresowo (co rok) będzie zwracał dokładnie takie same wyniki „losowania”.

Dodatkowo, ponieważ losujemy jedną z 10 000 możliwości (czyli kombinacje czterocyfrowe od 0000 do 9999), w naturalny sposób wyniki w pewnym momencie zaczną się powtarzać. Jest to oczywiste – jeśli siedem razy rzucisz zwykłą sześcienną kostką do gry, siłą rzeczy musisz uzyskać przynajmniej jedno powtórzenie. Nikt nie będzie przy tym podejrzewał, że kostka jest oszukana. W opisanym przeze mnie przypadku możemy spodziewać się powtórzeń mniej-więcej co tydzień (czyli 10 000 minut), ale w praktyce pierwszy dubel pojawi się już po paru minutach.

A sam rozkład wartości algorytmu w czasie na cały rok możesz zobaczyć na górze wpisu.

Gdzie tu losowość?

Możesz teraz zadać sobie pytanie „no dobra, ale gdzie tu jest losowość”? I będziesz miał absolutną rację – jeśli znasz sposób wygenerowania ziarna i algorytm obliczeń, jesteś w stanie przewidzieć jaki wynik da „losowanie”.

Ale jeśli popatrzysz tylko na wyniki, raczej nie znajdziesz szybkiego sposobu na powiązanie liczb 4161 i 625. A gdy wykorzystasz ten sam algorytm za rok, prawdopodobnie nie będziesz pamiętał, że wcześniej dostałeś dokładnie te same wyniki. Dlatego takie liczby nazywane są pseudolosowymi. Chociaż wcale nie zostały wylosowane, z punktu widzenia człowieka bardzo dobrze sprawdzą się jako losowe.

Pseudolosowanie w praktyce

Takie rozwiązanie jest o wiele tańsze niż prawdziwe losowanie, więc jest często stosowane w programowaniu.

O zastosowaniu w arkuszach kalkulacyjnych już napisałem.

Prostym przykładem, gdzie możesz zaobserwować pseudolosowanie jest generowanie nowego świata w „Minecrafcie” (niezależnie czy grasz Ty, czy Twoje dziecko). Gdy uruchomisz nową grę, zobaczysz informację o wykorzystanym numerze ziarna. Jest to liczba pomiędzy  -9 223 372 036 854 775 808 a 9 223 372 036 854 775 807. Daje to trochę możliwości i są małe szanse, że w ciągu życia dwa razy zagrasz na dokładnie takiej samej mapie. Z punktu widzenia gracza można więc powiedzieć, że gra zawsze generuje losowy i niepowtarzalny świat. Dodatkowo, system taki pozwala też pójść w drugą stronę – korzystając z opcji podania ziarna masz pewność, że wpisując tę samą liczbę dostaniesz zawsze taki sam obszar gry.

Podobnie działają aplikacje używane do logowania dwuetapowego (Google Authenticator, Microsoft Authenticator itp. – przy okazji, polecam ich używać, jeśli nie masz klucza U2F). Gdy taka aplikacja łączy się z konkretnym serwisem po raz pierwszy, wymienia z nim klucz, który może zawierać litery i cyfry. Żeby wyznaczyć kod jednorazowy, trzeba wziąć liczbę opartą na aktualnym czasie (z dokładnością do 30 sekund, bo co tyle kody się odświeżają), połączyć ją z wymienionym kluczem wcześniej kluczem, przeliczyć wszystko na wartość liczbową (w ten sposób dostajemy ziarno) i odpowiednio przetworzyć. Ponieważ klucz jest ustalony raz na zawsze, a zarówno Twój telefon, jak i serwer mają dostęp do aktualnego czasu, te same operacje mogą być wykonane niezależnie po obydwu stronach (nawet gdy nie masz połączenia z internetem) i zawsze dadzą ten sam wynik. Serwer sprawdza więc, czy  wpisany przez Ciebie kod jest taki sam, jak on sobie wyliczył (a dokładniej: czy ich zahaszowane wersje się zgadzają) i na tej podstawie pozwala Ci się zalogować.

W profesjonalnych zastosowaniach stosuje się dłuższe ziarno, niż podałem w przykładzie w tym wpisie (dla „Minecrafta” jest to 19 znaków, Google Authenticator używa chyba klucza 25-znakowego), do którego wygenerowania można użyć praktycznie każdej dostępnej danej: czasu, parametrów Twojego komputera, wyników giełdowych, danych pogodowych… Sposób przetwarzania ziarna też może być bardziej skomplikowany, niż opisany powyżej (i często jest bardzo dobrze chroniony). Ale zasada działania jest taka sama.

Swoją drogą: ciekawe, czy uczniowie w którymś e-dzienniku już rozgryźli, jakie „szczęśliwe numerki’ wypadną w konkretny dzień.

Czy komputer potrafi zrobić prawdziwe losowanie?

Możesz się teraz zastanawiać, czy w komputerze można przeprowadzić prawdziwe losowanie. Odpowiedź brzmi „tak”, ale wymaga to połączenia systemu z prawdziwym zjawiskiem losowym, które zachodzi poza komputerem. Przykładem takiego zjawiska (poza losowaniem Lotto albo rzutem kostką) może być rejestracja szumów matrycy aparatu cyfrowego (czyli zrobienia zdjęcia z zasłoniętym obiektywem) albo zdjęcie lampy wodnej z woskiem. Na filmach możesz zobaczyć, jak wyglądają prawdziwe generatory liczb losowych w praktyce:

Przyznasz, że pseudolosowanie wydaje się teraz kuszącą alternatywą dla programistów, prawda?

A jakby tak „odlosować” liczby?

Pewnie niektórym z Was już pojawił się w głowie pomysł „OK, to spróbujmy teraz rozgryźć algorytm na podstawie tego, jakie liczby z niego wychodzą”.

Teoretycznie – jasne, da się.

W praktyce – sprawdź sam. Poniżej znajdziesz 35 kolejnych wyników algorytmu generującego liczby sześciocyfrowe. Zastanów się czy jesteś w stanie odgadnąć, jak powstały:

746504 511713 425149 515404 196375 923416 550130 184756 915392 953589 0 59200 972181 350888 151448 853133 196375 746504 444997 837077 382300 702579 453453 991296 128737 621568 560059 128737 515404 702579 312875 934528 425149 717187 345408

Jeśli Ci się uda – daj znać w komentarzu. Wymyślę jakąś nagrodę:-).

Taki już urok liczb pseudolosowych. Jeśli znasz algorytm ich powstawania, są oczywiste. Jeśli widzisz same liczby, bardzo ciężko jest się zorientować, że mają ze sobą cokolwiek wspólnego.

Swoją drogą: zwykle spotykałem się z sześciocyfrowymi kodami do weryfikacji dwuetapowej. Oznacza to, że swoje bezpieczeństwo opieramy na prawdopodobieństwie jeden do miliona. Nie za wiele biorąc pod uwagę, że wyprodukowanie listy wszystkich takich liczb to dla komputera kwestia niecałej sekundy.  Przyjmując, że kod zmienia się co pół minuty (jak w Google Authenticator) i wypróbowanie jednej kombinacji zajmuje trzy sekundy (zależnie od szybkości połączenia i czasu odpowiedzi serwera), daje to już szanse 1:100000, że włamywaczowi uda się trafić „na pałę”. Jakby nie patrzeć: całkiem spore ryzyko jak na barierę chroniącą całe nasze cyfrowe życie. Dlatego warto, oprócz logowania wieloetapowego, włączyć na swoich kontach limit prób logowania. I powiadomienie o każdym zalogowaniu się w krytycznych usługach.

A morał z tego taki, że czasem taniej i szybciej jest zgadywać, niż rozgryzać algorytm.

Czas powiedzieć „sprawdzam”

Na koniec tylko zasygnalizuję temat, który mogę wziąć na warsztat w przyszłości: czy patrząc na serię liczb jesteś w stanie stwierdzić, że jest on losowa?

Krótka odpowiedź brzmi: tak.

Dłuższa: może nie do końca, ale można porównać zachowanie zbioru liczb pseudolosowych z naprawdę losowymi.

Są zestawy testów które pozwalają określić, czy masz do czynienia z liczbami losowymi, czy tylko takowe udającymi. Polegają one na sprawdzeniu charakterystyki zbioru liczb pod kątem np. rozkładu otrzymanych wartości, liczby powtórzeń, występowaniu w nich ciągów kolejnych lub takich samych liczb i tym podobnych parametrów. Na podstawie porównania wyników z wartościami dla prawdziwie losowego zbioru można stwierdzić, czy podane liczby zachowują się tak samo, jak losowane.

A jeśli zachowują się tak samo, to pseudolosowość wystarczy.

Jeśli chcecie, o szczegółach takich testów mogę opowiedzieć w innym wpisie.

Do zapamiętania

Jeśli zainteresowały Cię szczegóły techniczne i obliczeniowe, zachęcam do dalszego badania tematu i dyskusji pod wpisem. Jeśli nie – chciałbym, żebyś teraz już wiedział:

  • że w wielu miejscach spotykasz liczby, które dla Ciebie wyglądają na losowe, ale wcale takie nie są,
  • skąd się biorą liczby pseudolosowe,
  • że często na takich liczbach opiera się na nich bezpieczeństwo Twoich danych.

Jeśli wyciągnąłeś z tego wpisu dla siebie coś więcej, to już naprawdę super.

Zanim zamkniesz tę zakładkę

Teraz chciałem Cię poprosić, żebyś dał znać w komentarzu, co sądzisz o takich wpisach. Czy tematyka, styl i zakres wpisu był dla Ciebie OK, a może o jakich podobnych sprawach chciałbyś poczytać. Jeśli gdzieś napisałem coś głupiego, też koniecznie daj znać.

Jeśli wpis bardzo Ci się spodobał i chcesz mocno kibicować kontynuacji, możesz dorzucić mi coś przez buycoffee.

Postaw mi kawę na buycoffee.to

A jeśli chcesz zostać ze mną w kontakcie i nie martwić się tym, czy nie przegapisz następnego wpisu z tej serii, zapisz się na newsletter

Zapisując się na newsletter wyrażasz zgodę na przetwarzanie Twoich danych osobowych zgodnie z polityką prywatności w celu otrzymywania powiadomień o nowych wpisach i wydarzeniach związanych z blogiem. Nie będę Cię spamował. Będziesz mógł w każdej chwili zrezygnować z subskrypcji.