Add salt for every single user

This commit is contained in:
Unknown 2014-04-06 16:10:57 -04:00
parent db1fe3483e
commit e7c8a3cb8d
8 changed files with 64 additions and 30 deletions

View file

@ -7,7 +7,6 @@ github.com/go-martini/martini =
github.com/Unknwon/com = github.com/Unknwon/com =
github.com/Unknwon/cae = github.com/Unknwon/cae =
github.com/Unknwon/goconfig = github.com/Unknwon/goconfig =
github.com/dchest/scrypt =
github.com/nfnt/resize = github.com/nfnt/resize =
github.com/lunny/xorm = github.com/lunny/xorm =
github.com/go-sql-driver/mysql = github.com/go-sql-driver/mysql =

View file

@ -5,9 +5,9 @@ Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language
![Demo](http://gowalker.org/public/gogs_demo.gif) ![Demo](http://gowalker.org/public/gogs_demo.gif)
##### Current version: 0.2.1 Alpha ##### Current version: 0.2.2 Alpha
#### Due to testing purpose, data of [try.gogits.org](http://try.gogits.org) has been reset in March 29, 2014 and will reset multiple times after. Please do NOT put your important data on the site. #### Due to testing purpose, data of [try.gogits.org](http://try.gogits.org) has been reset in April 6, 2014 and will reset multiple times after. Please do NOT put your important data on the site.
#### Other language version #### Other language version

View file

@ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。
![Demo](http://gowalker.org/public/gogs_demo.gif) ![Demo](http://gowalker.org/public/gogs_demo.gif)
##### 当前版本0.2.1 Alpha ##### 当前版本0.2.2 Alpha
## 开发目的 ## 开发目的

View file

@ -19,7 +19,7 @@ import (
// Test that go1.2 tag above is included in builds. main.go refers to this definition. // Test that go1.2 tag above is included in builds. main.go refers to this definition.
const go12tag = true const go12tag = true
const APP_VER = "0.2.1.0406 Alpha" const APP_VER = "0.2.2.0406 Alpha"
func init() { func init() {
base.AppVer = APP_VER base.AppVer = APP_VER

View file

@ -5,6 +5,7 @@
package models package models
import ( import (
"crypto/sha256"
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
@ -13,8 +14,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/dchest/scrypt"
"github.com/gogits/git" "github.com/gogits/git"
"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
@ -62,6 +61,7 @@ type User struct {
IsActive bool IsActive bool
IsAdmin bool IsAdmin bool
Rands string `xorm:"VARCHAR(10)"` Rands string `xorm:"VARCHAR(10)"`
Salt string `xorm:"VARCHAR(10)"`
Created time.Time `xorm:"created"` Created time.Time `xorm:"created"`
Updated time.Time `xorm:"updated"` Updated time.Time `xorm:"updated"`
} }
@ -89,10 +89,9 @@ func (user *User) NewGitSig() *git.Signature {
} }
// EncodePasswd encodes password to safe format. // EncodePasswd encodes password to safe format.
func (user *User) EncodePasswd() error { func (user *User) EncodePasswd() {
newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte(base.SecretKey), 16384, 8, 1, 64) newPasswd := base.PBKDF2([]byte(user.Passwd), []byte(user.Salt), 10000, 50, sha256.New)
user.Passwd = fmt.Sprintf("%x", newPasswd) user.Passwd = fmt.Sprintf("%x", newPasswd)
return err
} }
// Member represents user is member of organization. // Member represents user is member of organization.
@ -148,9 +147,9 @@ func RegisterUser(user *User) (*User, error) {
user.Avatar = base.EncodeMd5(user.Email) user.Avatar = base.EncodeMd5(user.Email)
user.AvatarEmail = user.Email user.AvatarEmail = user.Email
user.Rands = GetUserSalt() user.Rands = GetUserSalt()
if err = user.EncodePasswd(); err != nil { user.Salt = GetUserSalt()
return nil, err user.EncodePasswd()
} else if _, err = orm.Insert(user); err != nil { if _, err = orm.Insert(user); err != nil {
return nil, err return nil, err
} else if err = os.MkdirAll(UserPath(user.Name), os.ModePerm); err != nil { } else if err = os.MkdirAll(UserPath(user.Name), os.ModePerm); err != nil {
if _, err := orm.Id(user.Id).Delete(&User{}); err != nil { if _, err := orm.Id(user.Id).Delete(&User{}); err != nil {
@ -384,18 +383,20 @@ func GetUserByEmail(email string) (*User, error) {
// LoginUserPlain validates user by raw user name and password. // LoginUserPlain validates user by raw user name and password.
func LoginUserPlain(name, passwd string) (*User, error) { func LoginUserPlain(name, passwd string) (*User, error) {
user := User{LowerName: strings.ToLower(name), Passwd: passwd} user := User{LowerName: strings.ToLower(name)}
if err := user.EncodePasswd(); err != nil {
return nil, err
}
has, err := orm.Get(&user) has, err := orm.Get(&user)
if err != nil { if err != nil {
return nil, err return nil, err
} else if !has { } else if !has {
err = ErrUserNotExist return nil, ErrUserNotExist
} }
return &user, err
newUser := &User{Passwd: passwd, Salt: user.Salt}
newUser.EncodePasswd()
if user.Passwd != newUser.Passwd {
return nil, ErrUserNotExist
}
return &user, nil
} }
// Follow is connection request for receiving user notifycation. // Follow is connection request for receiving user notifycation.

View file

@ -6,12 +6,14 @@ package base
import ( import (
"bytes" "bytes"
"crypto/hmac"
"crypto/md5" "crypto/md5"
"crypto/rand" "crypto/rand"
"crypto/sha1" "crypto/sha1"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"hash"
"math" "math"
"strconv" "strconv"
"strings" "strings"
@ -40,6 +42,44 @@ func GetRandomString(n int, alphabets ...byte) string {
return string(bytes) return string(bytes)
} }
// http://code.google.com/p/go/source/browse/pbkdf2/pbkdf2.go?repo=crypto
func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
prf := hmac.New(h, password)
hashLen := prf.Size()
numBlocks := (keyLen + hashLen - 1) / hashLen
var buf [4]byte
dk := make([]byte, 0, numBlocks*hashLen)
U := make([]byte, hashLen)
for block := 1; block <= numBlocks; block++ {
// N.B.: || means concatenation, ^ means XOR
// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
// U_1 = PRF(password, salt || uint(i))
prf.Reset()
prf.Write(salt)
buf[0] = byte(block >> 24)
buf[1] = byte(block >> 16)
buf[2] = byte(block >> 8)
buf[3] = byte(block)
prf.Write(buf[:4])
dk = prf.Sum(dk)
T := dk[len(dk)-hashLen:]
copy(U, T)
// U_n = PRF(password, U_(n-1))
for n := 2; n <= iter; n++ {
prf.Reset()
prf.Write(U)
U = U[:0]
U = prf.Sum(U)
for x := range U {
T[x] ^= U[x]
}
}
}
return dk[:keyLen]
}
// verify time limit code // verify time limit code
func VerifyTimeLimitCode(data string, minutes int, code string) bool { func VerifyTimeLimitCode(data string, minutes int, code string) bool {
if len(code) <= 18 { if len(code) <= 18 {

View file

@ -73,11 +73,7 @@ func SettingPassword(ctx *middleware.Context, form auth.UpdatePasswdForm) {
user := ctx.User user := ctx.User
newUser := &models.User{Passwd: form.NewPasswd} newUser := &models.User{Passwd: form.NewPasswd}
if err := newUser.EncodePasswd(); err != nil { newUser.EncodePasswd()
ctx.Handle(200, "setting.SettingPassword", err)
return
}
if user.Passwd != newUser.Passwd { if user.Passwd != newUser.Passwd {
ctx.Data["HasError"] = true ctx.Data["HasError"] = true
ctx.Data["ErrorMsg"] = "Old password is not correct" ctx.Data["ErrorMsg"] = "Old password is not correct"
@ -85,6 +81,7 @@ func SettingPassword(ctx *middleware.Context, form auth.UpdatePasswdForm) {
ctx.Data["HasError"] = true ctx.Data["HasError"] = true
ctx.Data["ErrorMsg"] = "New password and re-type password are not same" ctx.Data["ErrorMsg"] = "New password and re-type password are not same"
} else { } else {
newUser.Salt = models.GetUserSalt()
user.Passwd = newUser.Passwd user.Passwd = newUser.Passwd
if err := models.UpdateUser(user); err != nil { if err := models.UpdateUser(user); err != nil {
ctx.Handle(200, "setting.SettingPassword", err) ctx.Handle(200, "setting.SettingPassword", err)

View file

@ -477,12 +477,9 @@ func ResetPasswd(ctx *middleware.Context) {
} }
u.Passwd = passwd u.Passwd = passwd
if err := u.EncodePasswd(); err != nil {
ctx.Handle(404, "user.ResetPasswd(EncodePasswd)", err)
return
}
u.Rands = models.GetUserSalt() u.Rands = models.GetUserSalt()
u.Salt = models.GetUserSalt()
u.EncodePasswd()
if err := models.UpdateUser(u); err != nil { if err := models.UpdateUser(u); err != nil {
ctx.Handle(404, "user.ResetPasswd(UpdateUser)", err) ctx.Handle(404, "user.ResetPasswd(UpdateUser)", err)
return return