-
Notifications
You must be signed in to change notification settings - Fork 178
/
legacy.go
72 lines (62 loc) · 2.25 KB
/
legacy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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
}