2014-04-13 11 views
8

Ecco un esempio di salatura e hashing di una determinata password in python.equivalente sale e hash in golang

import scrypt 
import os 

# Length of salt 
PW_SALT_BYTES = 32 
# Length of scrypt hash of passwords 
PW_HASH_BYTES = 64 
# test password 
password = "hello" 

salt = os.urandom(PW_SALT_BYTES).encode('hex') 
# hash(password, salt, N=1 << 14, r=8, p=1, buflen=64) 
hashed_password = scrypt.hash(str(password), salt.decode('hex'), buflen=PW_HASH_BYTES).encode('hex') 
print(hashed_password) 

Il che ci darebbe un hash e la stringa salate in cambio: -

4d1da45b401961fccb10e094ecd70ec79510f05483ca293d300bbd0024e35866ca39fe09fbc15f83a359431021a1ed9644f7d2b871b357e37a186300877edb18 

Come potrei implementare questo in golang?

risposta

15

Go non ha scrypt nella libreria standard ma esiste un'implementazione "ufficiale" nel repository go.crypto.

import (
    "crypto/rand" 
    "fmt" 
    "io" 
    "log" 

    "code.google.com/p/go.crypto/scrypt" 
) 

const (
    PW_SALT_BYTES = 32 
    PW_HASH_BYTES = 64 

    password = "hello" 
) 

func main() { 
    salt := make([]byte, PW_SALT_BYTES) 
    _, err := io.ReadFull(rand.Reader, salt) 
    if err != nil { 
     log.Fatal(err) 
    } 

    hash, err := scrypt.Key([]byte(password), salt, 1<<14, 8, 1, PW_HASH_BYTES) 
    if err != nil { 
     log.Fatal(err) 
    } 

    fmt.Printf("%x\n", hash) 
} 
+0

Questo appare come quello che stavo cercando pure ma sto equivoco qualcosa perché l'output risultante 'hash' (da golang) fa non corrisponde alla 'hashed_password' stampata nello script python? Stavo pensando che dovrebbero produrre lo stesso risultato poiché entrambe le password di test sono "ciao". –

+0

@CalvinCheng: stavi usando lo stesso sale confrontando le versioni di Python e Go? In caso contrario, è positivo che l'output sia diverso. –

+0

Sì. Stavo anche provando con un sale fisso e non corrispondono. Per l'esempio sopra, hai ragione che non dovrebbero corrispondere perché il sale viene generato casualmente. –

6

Sembra che ora Go abbia lo scrypt nella libreria ufficiale. Il suo subrepositoryx/crypto tra molte altre funzioni crittografiche ha un scrypt.

Ecco un esempio di come si può utilizzare:

package main 

import (
    "golang.org/x/crypto/scrypt" 
    "fmt" 
) 

func main(){ 
    salt := []byte("asdfasdf") 
    dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32) 

    fmt.Println(dk) 
    fmt.Println(err) 
} 
1

Invece di utilizzare scrypt, una grande libreria per hash in modo sicuro le password con sali casuali in Golang è golang.org/x/crypto/bcrypt, come indicato nel seguente risposta:

Bcrypt password hashing in Golang (compatible with Node.js)?

Un paio di vantaggi di utilizzare bcrypt invece di scrypt:

  1. Il sale viene generato automaticamente (e in modo casuale) tramite l'hashing di una password, in modo da non doversi preoccupare della generazione di sale.
  2. Quando si memorizzano le password con hash in un database, non è più necessario preoccuparsi di memorizzare il sale per ogni hash delle password.
  3. La sintassi è semplificata per l'hashing e il controllo delle password.
  4. L'hash prodotto da bcrypt include la versione di bcrypt, costo, sale e cipher, non solo il codice.

Ecco un esempio di utilizzo di bcrypt preso dalla risposta di cui sopra:

package main 

import (
    "golang.org/x/crypto/bcrypt" 
    "fmt" 
) 

func main() { 
    password := []byte("MyDarkSecret") 

    // Hashing the password with the default cost of 10 
    hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost) 
    if err != nil { 
     panic(err) 
    } 
    fmt.Println(string(hashedPassword)) 

    // Comparing the password with the hash 
    err = bcrypt.CompareHashAndPassword(hashedPassword, password) 
    fmt.Println(err) // nil means it is a match 
}