Пример #1
0
//
//	Login() logs in the user, using the stored
//	bycrypt hash.
//
//	The return values are:
//
//	- bool: if the password matches the hash
//	- bool: if the hash needs to be changed
//		in the database (can only true when the
//		password matches the hash)
//	- string: what the hash in the database
//		needs to be changed to (has contents if
//		and only if the hash needs to be
//		changed)
//
func (a *AuthContext) Login(userId uint, password, hashed string) (bool, bool, string) {
	if a.loggedIn {
		panic("User already logged in!")
	}

	bcryptErr := bcrypt.CompareHashAndPassword([]byte(hashed), []byte(password))
	if bcryptErr == bcrypt.ErrMismatchedHashAndPassword {
		return false, false, ""
	} else if bcryptErr != nil {
		panic(bcryptErr)
	}

	a.authtoken = generateAuthtoken()
	a.hasChanged = true
	a.loggedIn = true
	a.userId = userId

	currentCost, costErr := bcrypt.Cost([]byte(hashed))
	if costErr != nil {
		panic(costErr)
	}

	if currentCost != a.bcryptCost {
		newHash, newHashErr := bcrypt.GenerateFromPassword([]byte(password), a.bcryptCost)
		if newHashErr != nil {
			panic(newHashErr)
		}

		return true, true, string(newHash)
	} else {
		return true, false, ""
	}
}
Пример #2
0
func (c *config) IsCurrent(encoded []byte) (isCurrent bool, err error) {
	cost, err := bcrypt.Cost(encoded)
	if err == nil {
		isCurrent = cost >= c.Cost
	}
	return
}
Пример #3
0
func TestSpec(t *testing.T) {

	Convey("Encrypt Testing", t, func() {

		Convey("generateSalt()", func() {
			salt, err := generateSalt()
			So(err, ShouldBeNil)
			So(salt, ShouldNotBeBlank)
			So(len(salt), ShouldEqual, SaltLength)
		})

		Convey("hashPassword()", func() {
			salt, err := generateSalt()
			So(err, ShouldBeNil)

			hash, err := hashPassword(salt, "hershmahgersh")
			So(err, ShouldBeNil)
			So(hash, ShouldNotBeNil)

			cost, err := bcrypt.Cost([]byte(hash))
			So(err, ShouldBeNil)
			So(cost, ShouldEqual, EncryptCost)

			pw := combine(salt, string(hash))
			log.Printf("pw = %+v\n", pw)
			parsedSalt, parsedHash := getPWPieces(pw)
			So(salt, ShouldEqual, parsedSalt)
			So(string(hash), ShouldEqual, parsedHash)
		})

		Convey("->Encrypt()", func() {
			passString := "mmmPassword1"
			password, err := Encrypt(passString)
			So(err, ShouldBeNil)
			So(password, ShouldNotBeEmpty)

			salt, _ := getPWPieces(password)
			So(len(salt), ShouldEqual, SaltLength)
		})

		Convey("->IsMatch()", func() {
			password := "******"
			hash, err := Encrypt(password)
			So(err, ShouldBeNil)

			match, err := IsMatch(password, hash)
			So(match, ShouldBeTrue)
			So(err, ShouldBeNil)

			match, err = IsMatch("lolfail", hash)
			So(match, ShouldBeFalse)
			So(err, ShouldNotBeNil)

			match, err = IsMatch("Megaman49", hash)
			So(match, ShouldBeFalse)
			So(err, ShouldNotBeNil)
		})
	})
}
Пример #4
0
func (s *scheme) NeedsUpdate(stub string) bool {
	cost, err := bcrypt.Cost([]byte(stub))
	if err != nil {
		return false
	}

	return cost < s.Cost
}
Пример #5
0
Файл: api.go Проект: jwmaag/dex
// checkCost returns an error if the hash provided does not meet minimum cost requirement
func checkCost(hash []byte) error {
	actual, err := bcrypt.Cost(hash)
	if err != nil {
		return fmt.Errorf("parsing bcrypt hash: %v", err)
	}
	if actual < bcrypt.DefaultCost {
		return fmt.Errorf("given hash cost = %d, does not meet minimum cost requirement = %d", actual, bcrypt.DefaultCost)
	}
	return nil
}
func TestSpec(t *testing.T) {

	Convey("Authentication Testing", t, func() {

		Convey("generateSalt()", func() {
			salt := generateSalt(cDEFAULT_SALT_LENGTH)
			So(len(salt), ShouldBeGreaterThan, 0)
			So(len(salt), ShouldEqual, cDEFAULT_SALT_LENGTH)
		})

		Convey("combine()", func() {
			salt := generateSalt(cDEFAULT_SALT_LENGTH)
			password := "******"
			expectedLength := len(salt) + len(password)
			combo := combine(salt, []byte(password))

			So(len(combo), ShouldBeGreaterThan, 0)
			So(len(combo), ShouldEqual, expectedLength)
			So(bytes.Equal(combo[len(combo)-len(salt):], salt), ShouldBeTrue)
		})

		Convey("hashPassword()", func() {
			combo := combine(generateSalt(cDEFAULT_SALT_LENGTH), []byte("hershmahgersh"))
			hash := hashPassword(combo, CDEFAULT_ENCRYPT_COST)
			So(len(hash), ShouldBeGreaterThan, 0)

			cost, err := bcrypt.Cost([]byte(hash))
			if err != nil {
				log.Print(err)
			}
			So(cost, ShouldEqual, CDEFAULT_ENCRYPT_COST)
		})

		Convey("CreatePassword()", func() {
			passString := "mmmPassword1"
			pwd := CreatePassword(passString, cDEFAULT_SALT_LENGTH, CDEFAULT_ENCRYPT_COST)
			pass_struct := new(password)

			So(pwd, ShouldHaveSameTypeAs, pass_struct)
			So(len(pwd.hash), ShouldBeGreaterThan, 0)
			So(len(pwd.salt), ShouldBeGreaterThan, 0)
			So(len(pwd.salt), ShouldEqual, cDEFAULT_SALT_LENGTH)
		})

		Convey("comparePassword", func() {
			password := "******"
			passwordMeta := CreatePassword(password, cDEFAULT_SALT_LENGTH, CDEFAULT_ENCRYPT_COST)

			So(passwordMatch(password, passwordMeta.salt, passwordMeta.hash), ShouldBeTrue)
			So(passwordMatch("lolfail", passwordMeta.salt, passwordMeta.hash), ShouldBeFalse)
			So(passwordMatch("Megaman49", passwordMeta.salt, passwordMeta.hash), ShouldBeFalse)
		})
	})
}
Пример #7
0
func decodeConfiguration(decoder *json.Decoder) (*Configuration, error) {
	var config Configuration
	err := decoder.Decode(&config)
	if err != nil {
		return nil, err
	}
	if config.Version < 1 {
		return nil, fmt.Errorf("Invalid configuration version (must be > 0): %v", config.Version)
	}
	if len(config.Hosts) == 0 {
		return nil, fmt.Errorf("Invalid configuration: empty hosts")
	}
	twoFInc := (2 * int(config.F)) + 1
	if twoFInc > len(config.Hosts) {
		return nil, fmt.Errorf("F given as %v, requires minimum 2F+1=%v hosts but only %v hosts specified.",
			config.F, twoFInc, len(config.Hosts))
	}
	if config.MaxRMCount == 0 && twoFInc < 128 {
		config.MaxRMCount = uint8(2 * twoFInc)
	} else if int(config.MaxRMCount) < twoFInc {
		return nil, fmt.Errorf("MaxRMCount given as %v but must be at least 2F+1=%v.", config.MaxRMCount, twoFInc)
	}
	for idx, hostPort := range config.Hosts {
		port := common.DefaultPort
		hostOnly := hostPort
		if host, portStr, err := net.SplitHostPort(hostPort); err == nil {
			portInt64, err := strconv.ParseUint(portStr, 0, 16)
			if err != nil {
				return nil, err
			}
			port = int(portInt64)
			hostOnly = host
		}
		hostPort = net.JoinHostPort(hostOnly, fmt.Sprint(port))
		config.Hosts[idx] = hostPort
		if _, err := net.ResolveTCPAddr("tcp", hostPort); err != nil {
			return nil, err
		}
	}
	if len(config.Accounts) == 0 {
		return nil, errors.New("No accounts defined")
	} else {
		for un, pw := range config.Accounts {
			if cost, err := bcrypt.Cost([]byte(pw)); err != nil {
				return nil, fmt.Errorf("Error in password for account %v: %v", un, err)
			} else if cost < bcrypt.DefaultCost {
				return nil, fmt.Errorf("Error in password for account %v: cost too low (%v)", un, cost)
			}
		}
	}
	return &config, err
}
Пример #8
0
func (p *password) UnmarshalJSON(b []byte) error {
	var data struct {
		Email    string `json:"email"`
		Username string `json:"username"`
		UserID   string `json:"userID"`
		Hash     string `json:"hash"`
	}
	if err := json.Unmarshal(b, &data); err != nil {
		return err
	}
	*p = password(storage.Password{
		Email:    data.Email,
		Username: data.Username,
		UserID:   data.UserID,
	})
	if len(data.Hash) == 0 {
		return fmt.Errorf("no password hash provided")
	}

	// If this value is a valid bcrypt, use it.
	_, bcryptErr := bcrypt.Cost([]byte(data.Hash))
	if bcryptErr == nil {
		p.Hash = []byte(data.Hash)
		return nil
	}

	// For backwards compatibility try to base64 decode this value.
	hashBytes, err := base64.StdEncoding.DecodeString(data.Hash)
	if err != nil {
		return fmt.Errorf("malformed bcrypt hash: %v", bcryptErr)
	}
	if _, err := bcrypt.Cost(hashBytes); err != nil {
		return fmt.Errorf("malformed bcrypt hash: %v", err)
	}
	p.Hash = hashBytes
	return nil
}
Пример #9
0
// Validate implements FieldValidator interface
func (v Password) Validate(value interface{}) (interface{}, error) {
	s, ok := value.(string)
	if !ok {
		if b, ok := value.([]byte); ok {
			// Maybe it's an already encoded version of the password
			if _, err := bcrypt.Cost(b); err == nil {
				return b, nil
			}
		}
		return nil, errors.New("not a string")
	}
	l := len(s)
	if l < v.MinLen {
		return nil, fmt.Errorf("is shorter than %d", v.MinLen)
	}
	if v.MaxLen > 0 && l > v.MaxLen {
		return nil, fmt.Errorf("is longer than %d", v.MaxLen)
	}
	b, err := bcrypt.GenerateFromPassword([]byte(s), v.Cost)
	if err != nil {
		return nil, err
	}
	return b, nil
}
Пример #10
0
func main() {
	var opts struct {
		Rounds   int    `short:"r" long:"rounds" default:"50000" description:"Number of rounds"`
		Hashname string `long:"hash" default:"sha256" description:"Hash to use"`
		Kdname   string `long:"kd" description:"Key derivation function"`
		Cost     int    `short:"c" long:"cost" default:"14" description:"Cost parameter to key derivation functions"`
		Hmacenc  string `long:"hmacenc" default:"" description:"Base64 encoded password for final hmac encryption step"`
	}
	opts.Rounds = 50000
	opts.Hashname = "sha256"
	opts.Kdname = "scrypt"
	opts.Cost = 14
	parser := flags.NewParser(&opts, flags.Default)
	parser.Usage = "[OPTIONS] <password> [salt]"
	parser.Usage += "\n\nSupported:\n"
	parser.Usage += "\tscrpyt bcrypt pbkdf2\n"
	args, err := parser.Parse()
	if err != nil {
		os.Exit(1)
	}
	if len(args) == 0 {
		log.Fatal("Error: ", "Parameter password missing")
	}

	if opts.Kdname == "bcrypt" && opts.Hmacenc != "" {
		log.Fatal("Error: bcrypt hash output can not be encrypted")
	}
	if opts.Kdname == "scrypt" {
		opts.Hashname = "sha256"
	}
	var hmacenc_bin []byte
	if opts.Hmacenc != "" {
		hmacenc_bin, err = base64.URLEncoding.DecodeString(opts.Hmacenc)
		if err != nil {
			log.Fatal("Unable to decode hmac encryption password: "******"Error: ", "Unknown hash given: ", opts.Hashname)
	}
	hashlength := h().Size()
	salt := make([]byte, hashlength)
	pw := []byte(args[0])
	if len(args) == 2 {
		if opts.Kdname == "bcrypt" {
			log.Fatal("Error: ", "Salt not supported for bcrypt")
		}
		salt, err = base64.URLEncoding.DecodeString(args[1])
		if err != nil {
			log.Fatal("Error: ", "Could not base64 decode salt: ", err)
		}
		if len(salt) != hashlength {
			log.Fatalf("Error: Salt not required size: %d needing %d bytes", len(salt), hashlength)
		}
	} else {
		n, err := rand.Read(salt)
		if n != len(salt) || err != nil {
			log.Fatal("Error: ", "Could not generate salt: ", err)
		}
	}
	var dk []byte

	switch opts.Kdname {
	case "pbkdf2":
		dk = pbkdf2.Key(pw, salt, opts.Rounds, hashlength, h)
	case "scrypt":
		dk, err = scrypt.Key(pw, salt, 1<<uint(opts.Cost), 8, 1, 32)
		if err != nil {
			log.Fatal("Error: ", "in scrypt: ", err)
		}
	case "bcrypt":
		if opts.Cost < bcrypt.MinCost || opts.Cost > bcrypt.MaxCost {
			log.Fatal("Error: ", "bcrypt: unsupported cost value")
		}
		dk, err = bcrypt.GenerateFromPassword(pw, opts.Cost)
		if err != nil {
			log.Fatal("Error: ", "in bcrypt: ", err)
		}
		// safeguard against bcrypt working with wrong cost value
		if real_cost, err := bcrypt.Cost(dk); err != nil {
			panic(err)
		} else if opts.Cost != real_cost {
			log.Fatal("Error: ", "bcrypt did not generate hash with user provided cost value")
		}
	default:
		log.Fatal("Error: unknown key derivation")
	}

	if opts.Hmacenc != "" {
		hmac_enc := hmac.New(h, hmacenc_bin)
		if _, err = hmac_enc.Write(dk); err != nil {
			log.Fatal("Error: error encrypting hash with hmac: ", err)
		}
		dk = hmac_enc.Sum(nil)
	}

	salt_b64 := base64.URLEncoding.EncodeToString(salt)
	pwhash_b64 := base64.URLEncoding.EncodeToString(dk)

	fmt.Printf("%s$%s\n", salt_b64, pwhash_b64)
	//fmt.Printf("%x\n", dk)
}