Czy istnieje sposób szyfrowania, który może przyjąć ciąg dowolnej długości i wygenerować skrót poniżej 10 znaków? Chcę tworzyć w miarę unikalne identyfikatory, ale oparte na treści wiadomości, a nie losowo.
Mogę jednak żyć z ograniczaniem wiadomości do wartości całkowitych, jeśli ciągi o dowolnej długości są niemożliwe. Jednak w takim przypadku skrót nie może być podobny dla dwóch kolejnych liczb całkowitych.
encryption
uniqueidentifier
rath3r
źródło
źródło
Odpowiedzi:
Możesz użyć dowolnego powszechnie dostępnego algorytmu haszującego (np. SHA-1), który da ci nieco dłuższy wynik niż potrzebujesz. Po prostu przytnij wynik do żądanej długości, co może być wystarczająco dobre.
Na przykład w Pythonie:
źródło
hash(a)
zderza się z,hash(b)
tobase64(hash(a))
również zderza się zbase64(hash(b))
.sha1
ale to już inna historia). Jeśli masz 10-znakowy hash, otrzymasz wyższą entropię, jeśli jest zakodowana za pomocąbase64
vsbase16
(lub hex). Jak wyżej? Zbase16
ciebie dostać 4 bitów informacji na znak, zebase64
ta jest 6bits / char. Łącznie 10-znakowy hash „hex” będzie miał 40 bitów entropii, a base64 60 bitów. Więc jest trochę bardziej odporny, przepraszam, jeśli nie byłem super jasny.Jeśli nie potrzebujesz algorytmu, który jest odporny na celowe modyfikacje, znalazłem algorytm o nazwie adler32, który daje dość krótkie (~ 8 znaków) wyniki. Wybierz go z menu rozwijanego, aby go wypróbować:
http://www.sha1-online.com/
źródło
Musisz zaszyfrować zawartość, aby uzyskać skrót. Dostępnych jest wiele skrótów, ale 10 znaków to dość mało dla zestawu wyników. Dawno temu ludzie używali CRC-32, który generuje 33-bitowy hash (w zasadzie 4 znaki plus jeden bit). Istnieje również CRC-64, który generuje 65-bitowy hash. MD5, który generuje 128-bitowy skrót (16 bajtów / znaków), jest uważany za uszkodzony do celów kryptograficznych, ponieważ można znaleźć dwie wiadomości, które mają ten sam skrót. Powinno być oczywiste, że za każdym razem, gdy utworzysz 16-bajtowe podsumowanie z wiadomości o dowolnej długości, otrzymasz duplikaty. Im krótszy skrót, tym większe ryzyko kolizji.
Jednak obawa, że hash nie będzie podobna dla dwóch kolejnych komunikatów (niezależnie od tego, czy są to liczby całkowite, czy nie), powinna być prawdziwa dla wszystkich skrótów. Nawet jedna drobna zmiana w oryginalnej wiadomości powinna skutkować bardzo odmiennym podsumowaniem.
Tak więc użycie czegoś takiego jak CRC-64 (i wynik bazowy-64) powinno znaleźć się w okolicy, której szukasz.
źródło
Podsumowując tylko odpowiedź, która była dla mnie pomocna (zwracając uwagę na komentarz @ erasmospunk o używaniu kodowania base-64). Moim celem było uzyskanie głównie krótkiego sznurka wyjątkowy ...
Nie jestem ekspertem, więc popraw to, jeśli zawiera jakieś rażące błędy (w Pythonie znowu jak zaakceptowana odpowiedź):
result
Tutaj używa więcej niż tylko znaki szesnastkowe (co można dostać, jeśli używanyhash.hexdigest()
), więc jest to mniej prawdopodobne, aby mieć kolizji (czyli powinno być bezpieczniej obciąć niż hex strawienia).Uwaga: użycie UUID4 (losowe). Zobacz http://en.wikipedia.org/wiki/Universally_unique_identifier dla innych typów.
źródło
Możesz użyć istniejącego algorytmu skrótu, który tworzy coś krótkiego, na przykład MD5 (128 bitów) lub SHA1 (160). Następnie możesz to jeszcze bardziej skrócić, XORując sekcje skrótu z innymi sekcjami. Zwiększy to ryzyko kolizji, ale nie tak źle, jak zwykłe obcięcie skrótu.
Możesz również uwzględnić długość oryginalnych danych jako część wyniku, aby uczynić go bardziej unikalnym. Na przykład XORowanie pierwszej połowy skrótu MD5 z drugą połową dałoby 64 bity. Dodaj 32 bity na długość danych (lub mniej, jeśli wiesz, że długość będzie zawsze pasować do mniejszej liczby bitów). Dałoby to wynik 96-bitowy (12-bajtowy), który można następnie przekształcić w 24-znakowy ciąg szesnastkowy. Alternatywnie możesz użyć kodowania podstawowego 64, aby było jeszcze krótsze.
źródło
Jeśli potrzebujesz,
"sub-10-character hash"
możesz użyć algorytmu Fletcher-32 , który generuje 8 znaków hash (32 bity), CRC-32 lub Adler-32 .CRC-32 jest wolniejszy od Adler32 o współczynnik 20% - 100%.
Fletcher-32 jest nieco bardziej niezawodny niż Adler-32. Ma niższy koszt obliczeniowy niż suma kontrolna Adlera: porównanie Fletchera i Adlera .
Przykładowy program z kilkoma implementacjami Fletchera jest podany poniżej:
Wynik:
Zgadza się z wektorami testowymi :
Adler-32 ma słabość do krótkich wiadomości zawierających kilkaset bajtów, ponieważ sumy kontrolne tych wiadomości mają słabe pokrycie 32 dostępnych bitów. Sprawdź to:
Algorytm Adler32 nie jest wystarczająco złożony, aby konkurować z porównywalnymi sumami kontrolnymi .
źródło
Po prostu uruchom to w terminalu (w systemie MacOS lub Linux):
Długość 8 znaków.
źródło
Możesz użyć biblioteki hashlib dla Pythona. W shake_128 i shake_256 algorytmy zapewniają mieszań zmienne długości. Oto działający kod (Python3):
Zwróć uwagę, że z parametrem długości x (na przykład 5) funkcja zwraca wartość skrótu o długości 2x .
źródło
Jest teraz 2019 i są lepsze opcje. Mianowicie xxhash .
źródło
Ostatnio potrzebowałem czegoś w rodzaju prostej funkcji redukcji strun. Zasadniczo kod wyglądał mniej więcej tak (kod C / C ++ z wyprzedzeniem):
Prawdopodobnie ma więcej kolizji, niż mogłoby się wydawać, ale nie jest przeznaczony do użytku jako kryptograficzna funkcja skrótu. Możesz wypróbować różne mnożniki (np. Zmienić 37 na inną liczbę pierwszą), jeśli masz zbyt wiele kolizji. Jedną z interesujących cech tego fragmentu jest to, że gdy Src jest krótszy niż Dest, Dest kończy się ciągiem wejściowym takim, jakim jest (0 * 37 + wartość = wartość). Jeśli chcesz mieć coś „czytelnego” na końcu procesu, Normalize dostosuje przekształcone bajty kosztem rosnących kolizji.
Źródło:
https://github.com/cubiclesoft/cross-platform-cpp/blob/master/sync/sync_util.cpp
źródło
DestSize
więcej niż 4 (32 bity), skoro sam hash jest tak kiepski? Jeśli chcesz, aby odporność na kolizje zapewniana przez wyjście większe niż int, użyłabyś SHA.