mirror of
https://github.com/ergochat/ergo.git
synced 2025-12-20 02:00:11 -08:00
refactor the password hashing / password autoupgrade system
This commit is contained in:
parent
6260869068
commit
dfb0a57040
18 changed files with 277 additions and 380 deletions
72
irc/legacy.go
Normal file
72
irc/legacy.go
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) 2018 Shivaram Lingamneni
|
||||
|
||||
package irc
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/tidwall/buntdb"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidPasswordHash = errors.New("invalid password hash")
|
||||
)
|
||||
|
||||
// Decode a hashed passphrase as it would appear in a config file,
|
||||
// retaining compatibility with old versions of `oragono genpasswd`
|
||||
// that used to apply a redundant layer of base64
|
||||
func decodeLegacyPasswordHash(hash string) ([]byte, error) {
|
||||
// a correctly formatted bcrypt hash is 60 bytes of printable ASCII
|
||||
if len(hash) == 80 {
|
||||
// double-base64, remove the outer layer:
|
||||
return base64.StdEncoding.DecodeString(hash)
|
||||
} else if len(hash) == 60 {
|
||||
return []byte(hash), nil
|
||||
} else {
|
||||
return nil, errInvalidPasswordHash
|
||||
}
|
||||
}
|
||||
|
||||
// helper to check a version 0 password hash, with global and per-passphrase salts
|
||||
func checkLegacyPasswordV0(hashedPassword, globalSalt, passphraseSalt []byte, passphrase string) error {
|
||||
var assembledPasswordBytes []byte
|
||||
assembledPasswordBytes = append(assembledPasswordBytes, globalSalt...)
|
||||
assembledPasswordBytes = append(assembledPasswordBytes, '-')
|
||||
assembledPasswordBytes = append(assembledPasswordBytes, passphraseSalt...)
|
||||
assembledPasswordBytes = append(assembledPasswordBytes, '-')
|
||||
assembledPasswordBytes = append(assembledPasswordBytes, []byte(passphrase)...)
|
||||
return bcrypt.CompareHashAndPassword(hashedPassword, assembledPasswordBytes)
|
||||
}
|
||||
|
||||
// checks a version 0 password hash; if successful, upgrades the database entry to version 1
|
||||
func handleLegacyPasswordV0(server *Server, account string, credentials AccountCredentials, passphrase string) (err error) {
|
||||
var globalSaltString string
|
||||
err = server.store.View(func(tx *buntdb.Tx) (err error) {
|
||||
globalSaltString, err = tx.Get("crypto.salt")
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
globalSalt, err := base64.StdEncoding.DecodeString(globalSaltString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = checkLegacyPasswordV0(credentials.PassphraseHash, globalSalt, credentials.PassphraseSalt, passphrase)
|
||||
if err != nil {
|
||||
// invalid password
|
||||
return err
|
||||
}
|
||||
|
||||
// upgrade credentials
|
||||
err = server.accounts.setPassword(account, passphrase)
|
||||
if err != nil {
|
||||
server.logger.Error("internal", fmt.Sprintf("could not upgrade user password: %v", err))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue