/
bcrypt_variant.go
89 lines (74 loc) · 2.22 KB
/
bcrypt_variant.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package crypt
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"github.com/go-crypt/x/bcrypt"
)
// NewBcryptVariant converts an identifier string to a Argon2Variant.
func NewBcryptVariant(identifier string) (variant BcryptVariant) {
switch identifier {
case AlgorithmPrefixBcrypt, algorithmPrefixBcryptA, algorithmPrefixBcryptY, algorithmPrefixBcryptX, "", "standard", "common":
return BcryptVariantStandard
case AlgorithmPrefixBcryptSHA256, digestSHA256:
return BcryptVariantSHA256
default:
return BcryptVariantNone
}
}
// BcryptVariant is a variant of the Argon2Digest.
type BcryptVariant int
const (
// BcryptVariantNone is a variant of the BcryptDigest which is unknown.
BcryptVariantNone BcryptVariant = iota
// BcryptVariantStandard is the standard variant of BcryptDigest.
BcryptVariantStandard
// BcryptVariantSHA256 is the variant of BcryptDigest which hashes the password with SHA-256.
BcryptVariantSHA256
)
// PasswordMaxLength returns -1 if the variant has no max length, otherwise returns the maximum password length.
func (v BcryptVariant) PasswordMaxLength() int {
switch v {
case BcryptVariantSHA256:
return -1
default:
return bcryptPasswordMaxLength
}
}
// Prefix returns the Argon2Variant prefix identifier.
func (v BcryptVariant) Prefix() (prefix string) {
switch v {
case BcryptVariantStandard:
return AlgorithmPrefixBcrypt
case BcryptVariantSHA256:
return AlgorithmPrefixBcryptSHA256
default:
return
}
}
// Encode formats the variant encoded Digest.
func (v BcryptVariant) Encode(cost int, version string, salt, key []byte) (f string) {
switch v {
case BcryptVariantStandard:
return fmt.Sprintf(StorageFormatBcrypt, version, cost, salt, key)
case BcryptVariantSHA256:
return fmt.Sprintf(StorageFormatBcryptSHA256, v.Prefix(), version, cost, salt, key)
default:
return
}
}
// EncodeInput returns the appropriate algorithm input.
func (v BcryptVariant) EncodeInput(src, salt []byte) (dst []byte) {
switch v {
case BcryptVariantSHA256:
h := hmac.New(sha256.New, bcrypt.Base64Encode(salt))
h.Write(src)
digest := h.Sum(nil)
dst = make([]byte, base64.StdEncoding.EncodedLen(len(digest)))
base64.StdEncoding.Encode(dst, digest)
return dst
default:
return src
}
}