Skróty wiadomości (ang. message digest, hash) to chleb powszedni w programowaniu. Przez funkcje md5(), sha1() itp. generowane są identyfikatory sesji, ciasteczka identyfikujące użytkownika, nazwy plików i tuzin innych rzeczy.
Skrót, jak sama nazwa wskazuje, powinien być krótki. Tymczasem w większości wypadków, z którymi się zetknąłem, skróty używane są w zapisie szesnastkowym, co oznacza, że 128 bitowy skrót MD5 jest zapisywany w 32 bajtach (czyli 256 bitach), a 160 bitowy SHA1 potrzebuje 40 znaków (256 bitów). To, delikatnie mówiąc, trąci rozrzutnością. Oszczędzić bajty można wykorzystując zapis base64, co pokazuje poniższy przykład:
var_dump(sha1('Ala ma kota')); var_dump(strtr(rtrim(base64_encode(sha1('Ala ma kota', true)), '='), '+/', '-_'));
Wynik:
string(40) "43fd70009a97a7d311c5644047ccc700f8d08a9d" string(27) "Q_1wAJqXp9MRxWRAR8zHAPjQip0"
Jak widać na powyższym przykładzie, w wypadku skrótu SHA1 oszczędność wynosi 13 bajtów czyli blisko 1/3. Gdyby było to ciasteczko to każde zapytanie HTTP do serwera wysyłane przez klienta byłoby krótsze o te 13 bajtów. Gdyby było to pole w bazie danych to na każdym wierszu oszczędność wynosiła by te 13 bajtów, a na dodatek wyszukiwanie wartości w tej kolumnie byłoby ciut szybsze. Potencjalne korzyści można by wymieniać dalej, a jeśli przemnożyć je przez setki użytkowników i tysiące odsłon to gra jest warta świeczki.
Tytułem wyjaśnienia: algorytm base64 zaokrągla wynik do wielokrotności 4 bajtów, brakujące dane uzupełnia znakami równości. Nie są one do niczego potrzebne, więc użyłem rtrim() do pozbycia się ewentualnych znaków równości na końcu. Z kolei strtr() zamienia znaki +
i /
które mają specjalne znaczenie w URL-ach i nazwach plików na odpowiednio -
i _
. Ten zabieg jest wymagany tylko jeśli skrót będzie wykorzystywany w URL-u albo nazwie pliku.