Hashing en adgangskode i Java

Java Top

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

1. Oversigt

I denne vejledning diskuterer vi vigtigheden af ​​adgangskodeshashing.

Vi tager et hurtigt kig på, hvad det er, hvorfor det er vigtigt, og nogle sikre og usikre måder at gøre det på Java.

2. Hvad er Hashing?

Hashing er processen med at generere en streng, eller hash, fra en given besked ved hjælp af en matematisk funktion kendt som en kryptografisk hash-funktion.

Mens der er flere hash-funktioner derude, skal de, der er skræddersyet til hashing-adgangskoder, have fire hovedegenskaber for at være sikre:

  1. Det bør være deterministisk: den samme besked behandlet af den samme hash-funktion skal altid producere det samme hash
  2. Det er ikke reversibel: det er upraktisk at generere en besked fra dens hash
  3. Det har højt entropi: en lille ændring til en besked skulle producere en meget anden hash
  4. Og det modstår kollisioner: to forskellige Beskeder skal ikke producere det samme hash

En hash-funktion, der har alle fire egenskaber, er en stærk kandidat til adgangskodeshashing, da de sammen dramatisk øger vanskeligheden ved reverse engineering af adgangskoden fra hash.

Men også password hashing-funktioner skal være langsomme. En hurtig algoritme vil hjælpe råstyrke angreb, hvor en hacker vil forsøge at gætte en adgangskode ved at hashing og sammenligne milliarder (eller trillioner) potentielle adgangskoder pr. sekund.

Nogle gode hash-funktioner, der opfylder alle disse kriterier erPBKDF2, BCrypt, og SCrypt. Men lad os først se på nogle ældre algoritmer, og hvorfor de ikke længere anbefales

3. Ikke anbefalet: MD5

Vores første hash-funktion er MD5-meddelelsesfordøjelsesalgoritmen, der blev udviklet helt tilbage i 1992.

Java'er MessageDigest gør dette let at beregne og kan stadig være nyttigt under andre omstændigheder.

I løbet af de sidste mange år har MD5 blev opdaget at mislykkes med den fjerde egenskab med adgangskodeshash ved at det blev beregningsmæssigt let at generere kollisioner. For at afslutte det er MD5 en hurtig algoritme og derfor ubrugelig mod brutale kraftangreb.

På grund af disse anbefales MD5 ikke.

4. Ikke anbefalet: SHA-512

Dernæst ser vi på SHA-512, som er en del af Secure Hash Algorithm-familien, en familie der startede med SHA-0 tilbage i 1993.

4.1. Hvorfor SHA-512?

Efterhånden som computere øges i strøm, og når vi finder nye sårbarheder, udleder forskere nye versioner af SHA. Nyere versioner har en gradvis længere længde, eller nogle gange offentliggør forskere en ny version af den underliggende algoritme.

SHA-512 repræsenterer den længste nøgle i algoritmens tredje generation.

Mens der er nu mere sikre versioner af SHA, SHA-512 er den stærkeste, der implementeres i Java.

4.2. Implementering i Java

Lad os nu se på implementering af SHA-512 hashing-algoritmen i Java.

Først skal vi forstå begrebet salt. Kort fortalt, dette er en tilfældig sekvens, der genereres for hver ny hash.

Ved at indføre denne tilfældighed øger vi hash'erne entropi, og vi beskytter vores database mod forudopstillede lister over hashes kendt som regnbue borde.

Vores nye hash-funktion bliver derefter omtrent:

salt <- generer-salt; hash <- salt + ':' + sha512 (salt + adgangskode)

4.3. Generering af et salt

For at indføre salt bruger vi SecureRandom klasse fra java.sikkerhed:

SecureRandom tilfældig = ny SecureRandom (); byte [] salt = ny byte [16]; random.nextBytes (salt);

Derefter bruger vi MessageDigest klasse for at konfigurere SHA-512 hash-funktion med vores salt:

MessageDigest md = MessageDigest.getInstance ("SHA-512"); md. opdatering (salt);

Og med det tilføjet, kan vi nu bruge fordøje metode til at generere vores hashede adgangskode:

byte [] hashedPassword = md.digest (passwordToHash.getBytes (StandardCharsets.UTF_8));

4.4. Hvorfor anbefales det ikke?

Når det anvendes med salt, er SHA-512 stadig en rimelig mulighed, men der er stærkere og langsommere muligheder derude.

Også de resterende muligheder, vi dækker, har en vigtig funktion: konfigurerbar styrke.

5. PBKDF2, BCrypt og SCrypt

PBKDF2, BCrypt og SCrypt er tre anbefalede algoritmer.

5.1. Hvorfor anbefales det?

Hver af disse er langsom, og hver har den strålende funktion at have en konfigurerbar styrke.

Dette betyder, at når computere øges i styrke, vi kan bremse algoritmen ved at ændre input.

5.2. Implementering af PBKDF2 i Java

Nu, salte er et grundlæggende princip i adgangskodeshashing, og så har vi også brug for en til PBKDF2:

SecureRandom tilfældig = ny SecureRandom (); byte [] salt = ny byte [16]; random.nextBytes (salt);

Derefter opretter vi en PBEKeySpec og en SecretKeyFactory som vi instantierer ved hjælp af PBKDF2WithHmacSHA1 algoritme:

KeySpec spec = ny PBEKeySpec (password.toCharArray (), salt, 65536, 128); SecretKeyFactory fabrik = SecretKeyFactory.getInstance ("PBKDF2WithHmacSHA1");

Den tredje parameter (65536) er faktisk styrkeparameteren. Det indikerer, hvor mange iterationer denne algoritme kører for, hvilket øger den tid det tager at producere hash.

Endelig kan vi bruge vores SecretKeyFactory at generere hash:

byte [] hash = factory.generateSecret (spec) .getEncoded ();

5.3. Implementering af BCrypt og SCrypt i Java

Så det viser sig, at BCrypt- og SCrypt-understøttelse leveres endnu ikke med Java, selvom nogle Java-biblioteker understøtter dem.

Et af disse biblioteker er Spring Security.

6. Password Hashing med Spring Security

Selvom Java naturligt understøtter både PBKDF2- og SHA-hashing-algoritmer, understøtter den ikke BCrypt- og SCrypt-algoritmer.

Heldigvis for os leveres Spring Security med support til alle disse anbefalede algoritmer via PasswordEncoder grænseflade:

  • MessageDigestPasswordEncoder giver os MD5 og SHA-512
  • Pbkdf2PasswordEncoder giver os PBKDF2
  • BCryptPasswordEncoder giver os BCrypt, og
  • SCryptPasswordEncoder giver os SCrypt

Adgangskodekoderne til PBKDF2, BCrypt og SCrypt leveres alle med understøttelse til konfiguration af den ønskede styrke af adgangskodeshash.

Vi kan bruge disse kodere direkte, selv uden at have en Spring Security-baseret applikation. Eller hvis vi beskytter vores websted med Spring Security, kan vi konfigurere vores ønskede kodeordskoder via dens DSL eller via afhængighedsinjektion.

Og i modsætning til vores eksempler ovenfor, disse krypteringsalgoritmer genererer saltet internt for os. Algoritmen lagrer saltet i output-hash til senere brug til validering af en adgangskode.

7. Konklusion

Så vi har taget et dybt dyk i adgangskodeshashing; udforske konceptet og dets anvendelser.

Og vi har kigget på nogle historiske hash-funktioner såvel som nogle, der i øjeblikket er implementeret, inden vi koder dem i Java.

Endelig så vi, at Spring Security leveres med sine adgangskodekrypterende klasser, der implementerer en række forskellige hash-funktioner.

Som altid er koden tilgængelig på GitHub.

Java bund

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN