Próbuję zrobić prosty konwerter String na SHA1 w Javie i oto, co mam ...
public static String toSHA1(byte[] convertme) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-1");
}
catch(NoSuchAlgorithmException e) {
e.printStackTrace();
}
return new String(md.digest(convertme));
}
Kiedy go toSHA1("password".getBytes())
zdaję [�a�ɹ??�%l�3~��.
, wiem, że to prawdopodobnie prosta poprawka do kodowania, taka jak UTF-8, ale czy ktoś może mi powiedzieć, co mam zrobić, aby uzyskać to, czego chcę, czyli 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
? A może robię to całkowicie źle?
SHA1
bez łącznika, nie wiem, czy to coś zmieni.getBytes()
, na przykład użyjtoSHA1("password".getBytes("UTF-8"))
Odpowiedzi:
AKTUALIZACJA
Możesz użyć Apache Commons Codec (wersja 1.7+), aby wykonać to zadanie za Ciebie.
Dzięki @ Jon Onstott za tę sugestię.
Stara odpowiedź
Zamień tablicę bajtów na ciąg szesnastkowy. Real's How To powie Ci, jak to zrobić .
i (skopiowane z Real's How To)
BTW, możesz uzyskać bardziej zwartą reprezentację przy użyciu Base64. Apache Commons Codec API 1.4 , ma to przyjemne narzędzie, które usuwa cały ból. patrz tutaj
źródło
DigestUtils.sha1Hex("my string")
zamiast wymyślać koło na nowo (chociaż warto wiedzieć, jak ręcznie przekonwertować na hex)?To jest moje rozwiązanie polegające na konwersji ciągu znaków na sha1. Działa dobrze w mojej aplikacji na Androida:
źródło
encryptPassword("test")
iecho test|sha1sum
w terminalu linux wyświetla ten sam wynik? Oni tego nie robią.echo test
, dane wyjściowe zawierające podział wiersza zostaną przesłane potokiem dosha1sum
. Jeśli chcesz haszować zwykły ciąg bez końca linii, możesz użyćecho -n test | sha1sum
.-n
Parametr sprawia,echo
pomijając podział wiersza.encryptPassword()
dźwięki są takie, jak używane do przechowywania danych uwierzytelniających. Zwróć uwagę, że kodowanie jest podatne na ataki słownikowe, ponieważ nie jest stosowane seeding. Sprawdź swoje środowisko bezpieczeństwa, czy nie stanowi to problemu dla Twojej aplikacji!Korzystanie z klasy Guava Hashing :
źródło
SHA-1 (i wszystkie inne algorytmy haszujące) zwracają dane binarne. Oznacza to, że (w Javie) tworzą plik
byte[]
. Tabyte
tablica nie reprezentuje żadnych konkretnych znaków, co oznacza, że nie możesz po prostu zmienić jej wString
taką, jaką zrobiłeś.Jeśli potrzebujesz a
String
, musisz sformatować tobyte[]
w sposób, który można przedstawić jako aString
(w przeciwnym razie po prostu zachowajbyte[]
wokół).Dwa powszechne sposoby przedstawiania dowolnych
byte[]
znaków drukowalnych to BASE64 lub proste ciągi szesnastkowe (tj. Reprezentowanebyte
przez dwie cyfry szesnastkowe). Wygląda na to, że próbujesz utworzyć ciąg szesnastkowy.Jest też inna pułapka: jeśli chcesz uzyskać SHA-1 w Javie
String
, musisz przekonwertować toString
nabyte[]
pierwszy (ponieważ wejście SHA-1 to równieżbyte[]
a). Jeśli po prostu użyjeszmyString.getBytes()
tak, jak pokazałeś, użyje domyślnego kodowania platformy i jako takie będzie zależne od środowiska, w którym go uruchomisz (na przykład może zwrócić różne dane na podstawie ustawień języka / ustawień regionalnych twojego systemu operacyjnego).Lepszym rozwiązaniem jest, aby określić kodowanie użyć do
String
-to-byte[]
konwersji tak:myString.getBytes("UTF-8")
. Wybór UTF-8 (lub innego kodowania, które może reprezentować każdy znak Unicode) jest tutaj najbezpieczniejszym wyborem.źródło
To proste rozwiązanie, którego można użyć podczas konwersji ciągu znaków na format szesnastkowy:
źródło
Po prostu użyj biblioteki kodeków Apache commons. Mają klasę narzędzi o nazwie DigestUtils
Nie ma potrzeby wchodzenia w szczegóły.
źródło
String result = DigestUtils.sha1Hex("An input string")
Jak wspomniano wcześniej, użyj kodeka Apache commons. Jest również polecany przez Springa (zobacz DigestUtils w dokumencie Spring). Na przykład:
Zdecydowanie nie użyłbym tutaj najwyżej ocenionej odpowiedzi.
źródło
Nie drukuje poprawnie, ponieważ musisz użyć kodowania Base64. W Javie 8 możesz kodować za pomocą klasy kodera Base64 .
Wynik
To da ci oczekiwaną wydajność
5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
źródło
Message Digest (hash) to bajt [] w bajcie []
Podsumowanie wiadomości jest zdefiniowane jako funkcja, która pobiera nieprzetworzoną tablicę bajtów i zwraca surową tablicę bajtów (aka
byte[]
). Na przykład SHA-1 (Secure Hash Algorithm 1) ma rozmiar skrótu 160 bitów lub 20 bajtów. Tablice surowych bajtów zwykle nie mogą być interpretowane jako kodowanie znaków, takie jak UTF-8 , ponieważ nie każdy bajt w każdej kolejności jest legalnym kodowaniem. Więc konwertuj je na aString
z:może tworzyć niedozwolone sekwencje lub ma wskaźniki kodu do niezdefiniowanych mapowań Unicode :
Kodowanie plików binarnych na tekst
W tym celu używane jest kodowanie binarne na tekst . W przypadku skrótów najczęściej używanym kodowaniem jest kodowanie HEX lub Base16 . Zasadniczo bajt może mieć wartość od
0
do255
(lub-128
do ze znakiem127
), która jest równoważna reprezentacji szesnastkowej0x00
-0xFF
. Dlatego hex podwoi wymaganą długość wyjścia, co oznacza, że 20-bajtowe wyjście utworzy ciąg o długości 40 znaków, np .:Zauważ, że nie jest wymagane stosowanie kodowania szesnastkowego. Możesz też użyć czegoś takiego jak base64 . Hex jest często preferowany, ponieważ jest łatwiejszy do odczytania przez ludzi i ma określoną długość wyjściową bez potrzeby wypełniania.
Możesz przekonwertować tablicę bajtów na szesnastkową za pomocą samej funkcjonalności JDK:
Zauważ jednak, że
BigInteger
zinterpretuje podaną tablicę bajtów jako liczbę a nie jako ciąg bajtów. Oznacza to, że wiodące zera nie zostaną wyprowadzone, a wynikowy ciąg może być krótszy niż 40 znaków.Używanie bibliotek do kodowania w formacie HEX
Możesz teraz skopiować i wkleić nieprzetestowaną metodę bajt-szesnastkowy ze Stack Overflow lub użyć ogromnych zależności, takich jak Guava .
Aby znaleźć rozwiązanie większości problemów związanych z bajtami, zaimplementowałem narzędzie do obsługi następujących przypadków: bytes-java (Github)
Aby przekonwertować tablicę bajtów skrótu wiadomości, możesz po prostu zrobić
lub możesz po prostu użyć wbudowanej funkcji skrótu
źródło
Podstawowa reprezentacja
SHA1
skrótu 64 :źródło
Powodem, dla którego to nie działa, jest to, że dzwoniąc
String(md.digest(convertme))
, mówisz Javie, aby zinterpretował sekwencję zaszyfrowanych bajtów jako ciąg. To, czego chcesz, to konwersja bajtów na znaki szesnastkowe.źródło
Konwertuj tablicę bajtów na ciąg szesnastkowy.
źródło