Use scrypt to store passwords

This commit is contained in:
Las Zenow 2014-06-30 23:06:55 -05:00
parent fdb7544999
commit 07a133e49a
4 changed files with 60 additions and 31 deletions

3
README
View file

@ -26,7 +26,8 @@ Yo also need to install go dependences:
# go get labix.org/v2/mgo/bson labix.org/v2/mgo/ github.com/gorilla/sessions \ # go get labix.org/v2/mgo/bson labix.org/v2/mgo/ github.com/gorilla/sessions \
github.com/gorilla/securecookie github.com/gorilla/mux \ github.com/gorilla/securecookie github.com/gorilla/mux \
github.com/nfnt/resize github.com/cihub/seelog \ github.com/nfnt/resize github.com/cihub/seelog \
gopkgs.com/unidecode.v1 gopkgs.com/unidecode.v1 \
code.google.com/p/go.crypto/scrypt
== Installation == == Installation ==
=== For admins ("for developers" below) === === For admins ("for developers" below) ===

View file

@ -9,7 +9,6 @@ const (
FS_BOOKS = "fs_books" FS_BOOKS = "fs_books"
FS_IMGS = "fs_imgs" FS_IMGS = "fs_imgs"
PASS_SALT = "ImperialLibSalt"
MINUTES_UPDATE_TAGS = 11 MINUTES_UPDATE_TAGS = 11
MINUTES_UPDATE_VISITED = 41 MINUTES_UPDATE_VISITED = 41
MINUTES_UPDATE_DOWNLOADED = 47 MINUTES_UPDATE_DOWNLOADED = 47

View file

@ -4,7 +4,8 @@ import log "github.com/cihub/seelog"
import ( import (
"bytes" "bytes"
"crypto/md5" "code.google.com/p/go.crypto/scrypt"
"crypto/rand"
"errors" "errors"
"labix.org/v2/mgo" "labix.org/v2/mgo"
"labix.org/v2/mgo/bson" "labix.org/v2/mgo/bson"
@ -24,6 +25,7 @@ type User struct {
type db_user struct { type db_user struct {
User string User string
Pass []byte Pass []byte
Salt []byte
Role string Role string
} }
@ -58,7 +60,11 @@ func addUser(coll *mgo.Collection, name string, pass string) error {
} }
var user db_user var user db_user
user.Pass = md5Pass(pass) user.Pass, user.Salt, err = hashPass(pass)
if err != nil {
log.Error("Error hashing password: ", err)
return errors.New("An error happen storing the password")
}
user.User = name user.User = name
user.Role = "" user.Role = ""
return coll.Insert(user) return coll.Insert(user)
@ -72,8 +78,7 @@ func (u User) Valid(pass string) bool {
if u.err != nil { if u.err != nil {
return false return false
} }
hash := md5Pass(pass) return validatePass(pass, u.user)
return bytes.Compare(u.user.Pass, hash) == 0
} }
func (u User) Role() string { func (u User) Role() string {
@ -84,13 +89,48 @@ func (u *User) SetPassword(pass string) error {
if u.err != nil { if u.err != nil {
return u.err return u.err
} }
hash := md5Pass(pass) hash, salt, err := hashPass(pass)
return u.coll.Update(bson.M{"user": u.user.User}, bson.M{"$set": bson.M{"pass": hash}}) if err != nil {
return err
}
return u.coll.Update(bson.M{"user": u.user.User}, bson.M{"$set": bson.M{"pass": hash, "salt": salt}})
} }
// FIXME: use a proper salting algorithm func hashPass(pass string) (hash []byte, salt []byte, err error) {
func md5Pass(pass string) []byte { salt, err = genSalt()
h := md5.New() if err != nil {
hash := h.Sum(([]byte)(pass_salt + pass)) return
return hash }
hash, err = calculateHash(pass, salt)
return
}
func genSalt() ([]byte, error) {
const (
saltLen = 64
)
b := make([]byte, saltLen)
_, err := rand.Read(b)
return b, err
}
func validatePass(pass string, user db_user) bool {
hash, err := calculateHash(pass, user.Salt)
if err != nil {
return false
}
return bytes.Compare(user.Pass, hash) == 0
}
func calculateHash(pass string, salt []byte) ([]byte, error) {
const (
N = 16384
r = 8
p = 1
keyLen = 32
)
bpass := []byte(pass)
return scrypt.Key(bpass, salt, N, r, p, keyLen)
} }

View file

@ -2,37 +2,26 @@ package main
import ( import (
"code.google.com/p/gopass" "code.google.com/p/gopass"
"crypto/md5" "git.gitorious.org/trantor/trantor.git/database"
"fmt"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
"os" "os"
) )
const ( const (
IP = "127.0.0.1" DB_IP = "127.0.0.1"
DB_NAME = "trantor" DB_NAME = "trantor"
USERS_COLL = "users"
PASS_SALT = "ImperialLibSalt"
) )
func main() { func main() {
session, err := mgo.Dial(IP) db := database.Init(DB_IP, DB_NAME)
if err != nil { defer db.Close()
panic(err)
}
defer session.Close()
coll := session.DB(DB_NAME).C(USERS_COLL)
user := os.Args[1] user := os.Args[1]
pass, err := gopass.GetPass("Password: ") pass, err := gopass.GetPass("Password: ")
if err != nil { if err != nil {
panic(err) panic(err)
} }
h := md5.New()
hash := h.Sum(([]byte)(PASS_SALT + pass)) err = db.AddUser(user, pass)
fmt.Println(user, " - ", hash)
err = coll.Insert(bson.M{"user": user, "pass": hash, "role": "admin"})
if err != nil { if err != nil {
panic(err) panic(err)
} }