Napisałem taki kod do generowania bezpiecznych ciągów znakowych :
function str_random(int $length = 16){ $token = ''; $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; for($i = 0; $i <= $strlen; $i ++){ } $token .= $hex_char_array[$hex_from_random]; } } } return $token; }
Tworzony jest tu ciąg ze znaków z puli a-zA-Z i 0-9, czyli podstawowe literki ASCII, bo taki jest wymóg. Przewertowałem internet i głównie z tego co tam piszą np na http://stackoverflow.com to coś takiego :
http://stackoverflow.com/questions/4356289...tring-generator
głównie próbuje się tam używać niezalecanych funkcji np rand() itp, albo jeżeli już ktoś jest mądrzejszy to korzysta z funkcji zalecanych przez PHP czyli np : openssl_random_pseudo_bytes manual: manualu, ale to jest żadkość , aby to znaleźć to trzeba specjalnie w google wpisać openssl_random_pseudo_bytes. Oczywiście, jak już napisałem ten kod powyżej, to znalazłem na tym forum taki oto przykład korzystający z array_rand, który jak widać jest bardzo prosty i robi w sumie to samo co założyłem. Pech chciał że przeszukując internet nie trafiłem na taki przykład, bo jest prosty i szybki mimo że też ta funkcja nie jest zalecana.
http://forum.php.pl/index.php?showtopic=114059
W sumie dodatkowe pytanie to o co chodzi z tym bezpieczeństwem , czy polegamy na opinii wydawcy który jak twierdzi że to się nie nadaje do celów związanych z bezpiecznym generowaniem liczb losowych to tak jest, czy jest inne jakieś wytłumaczenie o którym nie wiem.
Tak więc napisałem taki kod jak wyżej w oparciu o openssl_random_pseudo_bytes, bo takie przykłady przewijały się w lepszych przykładach na stronach don tego poświęconych. Mimo "fachowości" tych stron to kody te były dalekie od doskonałości mało tego powielały te same proste niedociągnięcia. Po pierwsze mało kto zwracał uwagę na oczywisty fakt, że openssl_random_pseudo_bytes po przerobieniu przez bin2hex() zwraca łańcuch tylko w formie szesnastkowego ciągu. Ciągu dużo prostszego i mocno ograniczonego, co przedkłada się na jego bezpieczeństwo itp. Wygląda też na to że ciąg z openssl_random_pseudo_bytes można tylko zamienić na postać szesnastkową, nigdzie w manualu PHP nie znalazłem metody która by potrafiła to zamienić w jakiś inny sposób, np znaki albo cyfry, ale pozostawić tak tego nie można. Na tych stronach często jednak zostawiano taki ciąg bez dalszej obróbki. W wielu z tych przykładów jakby nie zauważano, że podając parametr do długości ciągu i przerabiając go przez bin2hex, w wyniku dostajemy ciąg dwa razy dłuższy co jest wiadome, bo to jest reprezentacja szesnastkowa każdej liczby. Nie wiem może miałem pecha i tylko na takie przykłady natrafiałem, więc postanowiłem napisać taki kod sam jak powyżej zamieściłem. Przykłady ze znanej strony o programowaniu :
http://stackoverflow.com/questions/4356289...tring-generator
Dosyć dobry jest kod autora Arciszewski , bo krótki i faktycznie używający funkcji zalecanej przez PHP random_int(). Ale tam jest jakiś błąd, bo używa chyba starej funkcji :
mb_strlen wystarczy zmienić to na strlen i wszystko działa, krótki i działający.
Kilka słów jeszcze o moim kodzie dlaczego akurat tak a nie inaczej. Po pierwsze musimy sobie ustalić pule dozwolonych znaków z których może być zrobiony token, nie zawsze możemy go zrobić z dowolnych znaków, np klucze w tablicach przy nietypowym znaku wywalają błąd , aby temu zapobiec po to wymyślono base64_encode, ale to inna historia. Pulę zamieniłem na tablicę o kluczach odpowiadających znakom pochodzącym z łańcucha puli , nie na wartości w tablicy -to bardzo ważne. Teraz losujemy bezpieczny łańcuch szesnastkowy za pomocą openssl_random_pseudo_bytes. Oczywiście najprościej, by było zamienić wartości szesnastkowe na znaki, ale okazuje się że mogły by nie pasować do puli dozwolonych znaków. Po to jest tablica stworzona z puli dozwolonych znaaków, aby móc teraz wybrać/sprawdzić znaki. Wykonuje się to przez sprawdzanie istnienia zmiennej za pomocą isset(), bo jest to szybsze niż za każdym razem sprawdzanie wszystkich wartości tablicy. Ponieważ w losowym ciągu może być mniej znaków dozwolonych niż poszukujemy to powiększam to trzy krotnie na wszelki wypadek, oraz w funkcji,i jeśli token będzie zbyt krótki to tworzony jest nowy, tak więc jakby złożoność sie zwiększa.
No nie wiem, czy ten kod który napisałem jest coś wart, bo raz że długi dwa, że nie wiem czy tak naprawdę inaczej tego nie da sie zrobić. Proszę o opinie.