-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Provide the ability to set password hash algorithm parameters #22942
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
7cad01f
Provide the ability to set password hash algorithm parameters
zeripath 39b554a
prod drone
zeripath d79c546
placate the linter
zeripath 309ea1d
as per delvh
zeripath 16a8ce4
Merge branch 'main' into improve-hash-algo
jolheiser 47b282e
stop-using-argon2 in test hashes
zeripath b10e602
Try a slightly weaker version of the pbkdf2 algorithm
zeripath 2860567
Merge remote-tracking branch 'origin/main' into improve-hash-algo
zeripath 17f9402
oops
zeripath 66c95c5
More comments to be more explicit
zeripath 0dcd296
placate linter
zeripath 3e43075
add pbkdf2_hi to docs
zeripath 6707eec
Merge branch 'main' into improve-hash-algo
lunny 01768df
Merge branch 'main' into improve-hash-algo
lunny 1bb35b3
Merge branch 'main' into improve-hash-algo
lunny File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Copyright 2023 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package hash | ||
|
||
import ( | ||
"encoding/hex" | ||
"strings" | ||
|
||
"code.gitea.io/gitea/modules/log" | ||
"golang.org/x/crypto/argon2" | ||
jolheiser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
|
||
func init() { | ||
registerHasher("argon2", NewArgon2Hasher) | ||
} | ||
|
||
// Argon2Hasher implements PasswordHasher | ||
// and uses the Argon2 key derivation function, hybrant variant | ||
type Argon2Hasher struct { | ||
time uint32 | ||
memory uint32 | ||
threads uint8 | ||
keyLen uint32 | ||
} | ||
|
||
// HashWithSaltBytes a provided password and salt | ||
func (hasher *Argon2Hasher) HashWithSaltBytes(password string, salt []byte) string { | ||
if hasher == nil { | ||
return "" | ||
} | ||
return hex.EncodeToString(argon2.IDKey([]byte(password), salt, hasher.time, hasher.memory, hasher.threads, hasher.keyLen)) | ||
} | ||
|
||
// NewArgon2Hasher is a factory method to create an Argon2Hasher | ||
// The provided config should be either empty or of the form: | ||
// "<time>$<memory>$<threads>$<keyLen>", where <x> is the string representation | ||
// of an integer | ||
func NewArgon2Hasher(config string) *Argon2Hasher { | ||
// This default configuration uses the following parameters: | ||
// time=2, memory=64*1024, threads=8, keyLen=50. | ||
// It will make two passes through the memory, using 64MiB in total. | ||
hasher := &Argon2Hasher{ | ||
time: 2, | ||
memory: 1 << 16, | ||
threads: 8, | ||
keyLen: 50, | ||
} | ||
|
||
if config == "" { | ||
return hasher | ||
} | ||
|
||
vals := strings.SplitN(config, "$", 4) | ||
if len(vals) != 4 { | ||
log.Error("invalid argon2 hash spec %s", config) | ||
return nil | ||
} | ||
|
||
parsed, err := parseUIntParam(vals[0], "time", "argon2", config, nil) | ||
hasher.time = uint32(parsed) | ||
|
||
parsed, err = parseUIntParam(vals[1], "memory", "argon2", config, err) | ||
hasher.memory = uint32(parsed) | ||
|
||
parsed, err = parseUIntParam(vals[2], "threads", "argon2", config, err) | ||
hasher.threads = uint8(parsed) | ||
|
||
parsed, err = parseUIntParam(vals[3], "keyLen", "argon2", config, err) | ||
hasher.keyLen = uint32(parsed) | ||
if err != nil { | ||
return nil | ||
} | ||
|
||
return hasher | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Copyright 2023 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package hash | ||
|
||
import ( | ||
"golang.org/x/crypto/bcrypt" | ||
) | ||
|
||
func init() { | ||
registerHasher("bcrypt", NewBcryptHasher) | ||
} | ||
|
||
// BcryptHasher implements PasswordHasher | ||
// and uses the bcrypt password hash function. | ||
type BcryptHasher struct { | ||
cost int | ||
} | ||
|
||
// HashWithSaltBytes a provided password and salt | ||
func (hasher *BcryptHasher) HashWithSaltBytes(password string, salt []byte) string { | ||
if hasher == nil { | ||
return "" | ||
} | ||
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(password), hasher.cost) | ||
return string(hashedPassword) | ||
} | ||
|
||
func (hasher *BcryptHasher) VerifyPassword(password, hashedPassword, salt string) bool { | ||
return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) == nil | ||
} | ||
|
||
// NewBcryptHasher is a factory method to create an BcryptHasher | ||
// The provided config should be either empty or the string representation of the "<cost>" | ||
// as an integer | ||
func NewBcryptHasher(config string) *BcryptHasher { | ||
hasher := &BcryptHasher{ | ||
cost: 10, // cost=10. i.e. 2^10 rounds of key expansion. | ||
} | ||
|
||
if config == "" { | ||
return hasher | ||
} | ||
var err error | ||
hasher.cost, err = parseIntParam(config, "cost", "bcrypt", config, nil) | ||
if err != nil { | ||
return nil | ||
} | ||
|
||
return hasher | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright 2023 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package hash | ||
|
||
import ( | ||
"strconv" | ||
|
||
"code.gitea.io/gitea/modules/log" | ||
) | ||
|
||
func parseIntParam(value, param, algorithmName, config string, previousErr error) (int, error) { | ||
parsed, err := strconv.Atoi(value) | ||
if err != nil { | ||
log.Error("invalid integer for %s representation in %s hash spec %s", param, algorithmName, config) | ||
return 0, err | ||
} | ||
return parsed, previousErr // <- Keep the previous error as this function should still return an error once everything has been checked if any call failed | ||
} | ||
|
||
func parseUIntParam(value, param, algorithmName, config string, previousErr error) (uint64, error) { | ||
parsed, err := strconv.ParseUint(value, 10, 64) | ||
if err != nil { | ||
log.Error("invalid integer for %s representation in %s hash spec %s", param, algorithmName, config) | ||
return 0, err | ||
} | ||
return parsed, previousErr // <- Keep the previous error as this function should still return an error once everything has been checked if any call failed | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.