Java kryptografia hasła

0

Witam napisałem sobie taki testowy programik w javie:

public class AES {

    
     public static String asHex (byte buf[]) 
     {
      StringBuffer strbuf = new StringBuffer(buf.length * 2);
      int i;

      for (i = 0; i < buf.length; i++) {
       if (((int) buf[i] & 0xff) < 0x10)
	    strbuf.append("0");

       strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
      }

      return strbuf.toString();
     }

     public static void main(String[] args) throws Exception {

      

       // Get the KeyGenerator

       SecureRandom srandom = new SecureRandom();
       KeyGenerator kgen = KeyGenerator.getInstance("AES");
       kgen.init(256, srandom); // 192 and 256 bits may not be available

       // Generate the secret key specs.
       SecretKey skey = kgen.generateKey();
       byte[] raw = skey.getEncoded();

       SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");


       // Instantiate the cipher

       Cipher cipher = Cipher.getInstance("AES");

       cipher.init(Cipher.ENCRYPT_MODE, skeySpec ,srandom);
       
       
       byte[] encrypted = cipher.doFinal((args.length == 0 ?       "password" : args[0]).getBytes());
       
       System.out.println("encrypted string: " + asHex(encrypted));

       
       
       cipher.init(Cipher.DECRYPT_MODE, skeySpec);
       byte[] original =
         cipher.doFinal(encrypted);
       String originalString = new String(original);
       System.out.println("Original string: " +
         originalString + " " + asHex(original));
     }
}
 

Podpatrzyłem z innych przykładów na necie. Jako , że z kryptografią nie jestem za pan brat mam pytanko...
Chciałbym go użyć do szyfrowania hasła .
1.Czyli jak rozumiem user się rejestruje wtedy tworzę my hasło i zapisuję w postaci zaszyfrowanej i jak mniemam muszę także zapisać klucz szyfrujący ??

Czyli wygląda to tak : user się loguje tworzę klucz i szyfruję hasło czyli to moje :

cipher.init(Cipher.ENCRYPT_MODE, skeySpec ,srandom);       
       
       byte[] encrypted = cipher.doFinal((args.length == 0 ?       "password" : args[0]).getBytes()); 

2.Następnie muszę też przechować ten skeySpec ?? ale jak go przechować w bazie i jak go potem odtworzyć ??
Bo potem jak rozumiem user się loguje i muszę porównać to co wpisał w formularzu ze zdekodowanym hasłem
czyli moje:

//utworzenie SkeySpec z bazy danych ?? tylko jak ?
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
       byte[] original =
         cipher.doFinal(encrypted);
       String originalString = new String(original); 
  1. Mam jeszcze pytanko czy jest to dobre zabezpieczenie i czy metodologia postępowania według mnie jest poprawna ??

Dziękuję za odpowiedź

0

Najprostsze i chyba najlepsze rozwiazanie to bierzesz hasło z rejestracji i robisz hash funkcja skrotu np SHA1 i zapisujesz to do bazy. Potem przy logowaniu ta sama metoda z podanego hasla robisz hash i porownujesz z tym ktory masz w bazie. :)

0

ad 3. Metoda do d**y, a zabezpieczenie kiepskie.

Po pierwsze co zostało zaszyfrowane to może zostać odszyfrowane.
Po drugie przy szyfrowaniu musisz jakoś przechowywać klucz. Jak ktoś ukradnie klucz i zaszyfrowane hasła to równie dobrze możesz mu wysłać odszyfrowane hasła by nie marnował prądu na odszyfrowanie. Szczególnie, że trzymasz tu też jakąś relacje do klucza.
Po trzecie zamiast szyfrować użyj funkcji skrótu z tzw. solą. Najlepiej którejś z odmian SHA2 np. SHA512. Bierzesz hasło. Dodajesz na początku lub końcu losowy ciąg znaków - wspomnianą sól. Przepuszczasz przez funkcję haszującą. Do wyniku dodajesz sól użytą przy hashowaniu. W bazie trzymasz login, zahaszowane hasło.
Procedura sprawdzania hasła:

  1. pobierasz login i hasło z bazy.
  2. z hasła wydzielasz sól i "hasło właściwe".
  3. do hasła przesłanego przez użytkownika dodajesz sól
  4. otrzymany ciąg haszujesz
  5. Porównujesz z tym co masz w "haśle właściwym"
    Po czwarte zachęcasz użytkowników do tworzenia mocnych haseł (najłatwiej jest dopuścić używanie wszystkich znaków oraz dodać informację o sile hasła, ale nie zmuszasz do tworzenia w pokemonkodzie) oraz ich regularne zmienianie (tu można już bezczelnie wymuszać zmianę, po zalogowaniu jeżeli minął termin "przydatności do spożycia" dla hasła wyświetlasz tylko ekran zmiany hasła i nie ma przebacz).
0

1.Czyli w tej metodzie co ty napisałeś to nigdy nie będzie istniała możliwość podania hasła jeśli zostanie zapomniane przez usera (trzeba mu wygenerować nowe)
2.Jeśli chcemy dostatecznie się zabezpieczyć to pasuje także zhashować emaila do usera . Jeśli ktoś zgubi hasło to można mu odeslać na maila , a jeśli mail nie jest zhashowany w naszej bazie danych. To podczas ataku i przejęcia bazy osoba ta ma dostęp do maila danego usera. A złamanie poczty nie jest chyba dla nikogo trudne.
Ale jeśli zakodujemy emaila to pasowało by mieć także możliwość dekodowania ponieważ chcielibyśmy np wysyłać maile do danego usera ?? jak sobie wtedy poradzić z taką sytuacją ??
3. Są gdzieś jakieś przykłady z sha2, w necie jest dużo tego ale opisywane są tylko najprostsze przypadki czyli jak zakodować hasło ...
ale jak oddzielić sól od hasła właściwego i sprawdzić inne hasło to nie mogę znaleźć :/

Patrzyłem na taki przykład :
http://stackoverflow.com/questions/992019/java-256bit-aes-encryption
post: erickson

Czyli ta metoda jest też zła ??

Dzięki za odpowiedź

0
  1. Należy wtedy wygenerować nowe hasło. Jest to jednak bezpieczniejsza metoda niż trzymanie haseł w postaci zaszyfrowanej.
  2. I tak i nie. Z jednej strony włamanie się na pocztę jest stosunkowo trudne, a z drugiej dużo zależy od odpowiedzialności samego użytkownika. Można też zastosować np. "magic word", czyli mechanizm podobny do tego znanego z allegro. Przypomnienie hasła tylko po podaniu odpowiedzi na pytanie typu "Nazwisko panieńskie babki, kuzyna, wujka Zenona". Odpowiedź można zahaszować. Dopiero po podaniu poprawnej odpowiedzi wysyłamy hasło.
  3. https://www.owasp.org/index.php/Hashing_Java Polecam cały serwis .

Co do podanej metody to sam pomysł szyfrowania hasła jest nie teges. To co pisałem wcześniej - co zaszyfrowano to można odszyfrować. jedynym rozsądnym zastosowaniem jest sytuacja kiedy chcemy by aplikacja łączyła się jako zdalny klient z jakąś usługą wymagającą podania hasła. Chociaż i tu warto by użyć kluczy tak jak w przypadku usługi SSH.

0
  1. tylko mi chodzi o to że jeśli zakodujemy emaila. To jak potem wysłać jakieś powiadomienia na ten mail , w programie. Ok rozumiem że można użyć magic word aby user mugł odzyskać hasło. Ale mi chodzi głównie o mechanizm umożliwiający nam jako programiście używanie tego emaila w celu wysyłania powiadomień itp ....

Dzięki za odpowiedź i stronke

nie rozumiem jeszcze bardzo punktu 2 we wcześniejszej wypowiedzi:
2. z hasła wydzielasz sól i "hasło właściwe".

Skoro moje hasło zawiera sól + hasło właściwe i mogę wydzielić sól . To skoro ja mogę to ktoś kto przejął bazę chyba też może ?? Skoro napisałeś że dodajesz na początku lub na końcu losowy ciąg znaków wspomnianą sól ... Czyli osoba która przejęła bazę wie tylko tyle że sól jest albo na początku albo na końcu .. Chyba że ja źle rozumuje no nic poczytam jeszcze ...

0

Koziołek napisałeś:
w tedy trzymasz emial jako zwykły tekst. W najgorszym wypadku radochę będą mieli spamerzy. Jednak złamanie hasła będzie już znacznie trudniejsze

a jak zabezpieczyć się w przypadku kiedy ktoś niepowołany zmieni w bazie maila, wejdzie na stronę i da opcje zapomniałem hasła wtedy nowe wygenerowane hasło przyjdzie na jego maila ??

0

@lukasw44, jeżeli osoba niepowołana uzyska możliwość zmiany danych na serwerze to dupablada. Tu nawet nie chodzi o uzyskanie dostępu do konkretnego konta, bo ten nie będzie już potrzebny jeżeli możesz modyfikować dane bezpośrednio w bazie.

0

ale to jest dla kogoś pestka dostać dostęp do bazy danych np ja obecnie bawie się jboss7as (fajny serwerek polecam)

i tam np definiuje się nazwę użytkownika oraz hasło do bazy w pliku standalone.xml (zresztą w innych wersjach jbossa też definiuje się hasło oraz użytkownika w pliku xml z tego co kojarzę )

Więc jak ktoś niepowołany dostanie się na server to wystarczy sczytać i wie jaki server aplikacyjny jest używany no to raczej nie będzie miał problemu uzyskać dostęp ??
zresztą chyba na wszystkich zerwerach jee musimy definiować użytkownika oraz baze danych ?? nic tylko hackować ...

0
Koziołek napisał(a)
  1. pobierasz login i hasło z bazy.
  2. z hasła wydzielasz sól i "hasło właściwe".

w jaki sposób można to wydzielić, skoro sól jest losowym ciągiem znaków. Czy sól ma jakąś konkretną ustaloną długość, żebyśmy wiedzieli, gdzie się ona zaczyna?

czy znacie jakieś godne polecenia strony lub książki dotyczące zabezpieczeń programów i aplikacji webowych pisanych w javie? oprócz https://www.owasp.org/index.php/Hashing_Java

0

@Tompey, można w ten sposób, że znasz długość soli i jej położenie. Można też na kilka innych sposobów np.:
text > base64 > text+base64(sól) > sha2 > zahaszowane hasło, które jest "samosoloące się".

0

mam wrażenie, że chodzi im o coś takiego:

użytkownik podaje hasło(przy rejestracji, zmianie hasła) : qwerty123
programista(w skrypcie) do tego hasła dodaje ustalone przez siebie znaki na końcu bądź na początku: a2d-qwerty123
tekst jest hashowany funkcją sha256() i zapisywany do bazy.

teraz użytkownik próbuje się zalogować:
podaje hasło: qwerty123
do hasła(w skrypcie) dodawany na początku jest ciąg a2d- tak, że ciąg wygląda teraz a2d-qwerty123.
hashujemy tekst i porównujemy z tym co w bazie dla danego użyszkodnika :). Jeżeli ktoś dostanie się do naszej bazy to pod warunkiem, że nie zna soli jakiej używamy będzie miał mocno utrudnione poznanie haseł o ile w ogóle możliwe :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1