Hvordan Devise holder dine Rails-app-adgangskoder sikre

Devise er en utrolig godkendelsesløsning til Rails med mere end 40 millioner downloads. Men da det abstraherer de fleste af de kryptografiske operationer, er det ikke altid let at forstå, hvad der sker bag kulisserne.

En af disse abstraktioner kulminerer i vedholdenheden af ​​en encrypted_passworddirekte i databasen. Så jeg har altid været nysgerrig efter, hvad det faktisk repræsenterer. Her er et eksempel:

$2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO

Men hvad betyder det gibberish?

Devise bruger Bcrypt til at gemme oplysninger sikkert. På sin hjemmeside nævnes det, at det bruger “ OpenBSD bcrypt () password hashing algoritme, så du nemt kan gemme en sikker hash af dine brugeres adgangskoder ”. Men hvad er denne hash? Hvordan fungerer det, og hvordan holder det gemte adgangskoder sikre?

Det er det, jeg vil vise dig i dag.

Lad os arbejde baglæns - fra den gemte hash i din database til krypterings- og dekrypteringsprocessen.

Den hash $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yObestår faktisk af flere komponenter:

  • Bcrypt version ( 2a) - versionen af ​​bcrypt () algoritmen, der bruges til at producere denne hash (gemt efter det første $tegn)
  • Cost ( 11) - den omkostningsfaktor, der bruges til at oprette hash (gemt efter det andet $tegn)
  • Salt ( $2a$11$yMMbLgN9uY6J3LhorfU9iu) - en tilfældig streng, der når den kombineres med din adgangskode gør den unik (første 29 tegn)
  • Checksum ( LAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO) - den faktiske hashdel af den lagrede encrypted_password(resterende streng efter de 29 tegn)

Lad os undersøge de sidste 3 parametre:

  • Når du bruger Devise, indstilles Costværdien af ​​en klassevariabel kaldet stretches, og standardværdien er 11. Det specificerer antallet af gange, adgangskoden er hash. ( På din devise.rb-initialisering kan du konfigurere dette til en lavere værdi for testmiljøet for at få din testpakke til at køre hurtigere. ) *
  • Den salt er den tilfældig streng bruges til at kombinere med den oprindelige adgangskode. Dette er det, der får den samme adgangskode til at have forskellige værdier, når de opbevares krypteret. ( Se mere nedenfor om hvorfor det betyder noget, og hvad er Rainbow Table Attack s.) **
  • Den checksum er den faktiske genereret hash af adgangskoden efter at være kombineret med den tilfældige salt.

Når en bruger registrerer sig i din app, skal de indstille en adgangskode. Før denne adgangskode gemmes i databasen, genereres et tilfældigt salt via BCrypt :: Engine.generate_salt (omkostning) ved at tage hensyn til den tidligere nævnte omkostningsfaktor. (Bemærk: hvis pepperklassevariabelværdien er indstillet, føjes dens værdi til adgangskoden, inden den saltes.)

Med dette salt (f.eks. $2a$11$yMMbLgN9uY6J3LhorfU9iuSom inkluderer omkostningsfaktoren) kalder det BCrypt :: Engine.hash_secret (adgangskode, salt), der beregner den endelige hash, der skal lagres ved hjælp af det genererede salt og den adgangskode, der er valgt af brugeren. Denne sidste hash (for eksempel $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO) gemmes igen i encrypted_passwordkolonnen i databasen.

Men hvis denne hash ikke er reversibel, og saltet tilfældigt genereres ved BCrypt::Password.createopkaldet af BCrypt::Engine.generate_salt(cost), hvordan kan det så bruges til at logge på brugeren?

Det er her, de forskellige hash-komponenter er nyttige. Efter at have fundet den post, der matcher den e-mail, der leveres af brugeren til at logge på, hentes den krypterede adgangskode og opdelt i de forskellige komponenter, der er nævnt ovenfor ( Bcrypt-version , pris , salt og kontrolsum ).

Efter denne indledende forberedelse er her hvad der sker næste:

  1. Hente input adgangskode ( 1234)
  2. Hent saltet fra den gemte adgangskode ( $2a$11$yMMbLgN9uY6J3LhorfU9iu)
  3. Generer hash fra adgangskoden og salt ved hjælp af den samme bcrypt-version og omkostningsfaktor ( BCrypt::Engine.hash_secret(“1234”, “$2a$11$yMMbLgN9uY6J3LhorfU9iu”))
  4. Kontroller, om den gemte hash er den samme som beregnet i trin 3 ( $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO)

Og sådan gemmer Devise adgangskoder sikkert og beskytter dig mod en række angreb, selvom din database er kompromitteret.

Kontakt Twitter @alvesjtiago og fortæl mig, hvis du fandt denne artikel interessant! Tak fordi du læste.

PS: Jeg er på ingen måde en sikkerheds- eller kryptografiekspert, så kontakt venligst hvis du finder noget galt. Jeg håber, at ved at forenkle nogle af begreberne bliver det lettere at forstå, hvad der sker.

Tak @filipepina, @ivobenedito, @jackveiga, @joao_mags og @pedrosmmoreira for anmeldelserne og forslagene. Denne artikel er også tilgængelig på //blog.tiagoalves.me/how-does-devise-keep-your-passwords-safe.

Flere oplysninger om nogle af emnerne.

Omkostningsfaktor *

  • Fare for standard bcrypt-omkostningsfaktoren
  • Anbefalet antal runder for bcrypt

Rainbow bordangreb **

  • Rainbow bord - Wikipedia
  • Hvad er regnbue borde, og hvordan bruges de?