-
Notifications
You must be signed in to change notification settings - Fork 1
/
bcrypt.go
98 lines (88 loc) · 2.12 KB
/
bcrypt.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
90
91
92
93
94
95
96
97
98
package bcrypt
import (
"encoding/hex"
"errors"
"strings"
"github.com/aldy505/phc-crypto/format"
"golang.org/x/crypto/bcrypt"
)
// Config initialize the config require to create a hash function
type Config struct {
Rounds int
}
const (
// ROUNDS is the cost of rounds, minimum of 4, maximum of 31.
ROUNDS = 10
)
var ErrEmptyField error = errors.New("function parameters must not be empty")
// Hash creates a PHC-formatted hash with config provided
//
// import (
// "fmt"
// "github.com/aldy505/phc-crypto/bcrypt"
// )
//
// func main() {
// hash, err := bcrypt.Hash("password", bcrypt.Config{
// Rounds: 12,
// })
// if err != nil {
// fmt.Println(err)
// }
// fmt.Println(hash) // $bcrypt$v=0$r=12$$2432612431322479356256373563666e503557...
// }
func Hash(plain string, config Config) (string, error) {
if plain == "" {
return "", ErrEmptyField
}
if config.Rounds <= 0 {
config.Rounds = ROUNDS
}
hash, err := bcrypt.GenerateFromPassword([]byte(plain), config.Rounds)
if err != nil {
return "", err
}
hashString := format.Serialize(format.PHCConfig{
ID: "bcrypt",
Version: 0,
Params: map[string]interface{}{
"r": config.Rounds,
},
Hash: hex.EncodeToString(hash),
})
return hashString, nil
}
// Verify checks the hash if it's equal (by an algorithm) to plain text provided.
//
// import (
// "fmt"
// "github.com/aldy505/phc-crypto/bcrypt"
// )
//
// func main() {
// hash := "$bcrypt$v=0$r=12$$2432612431322479356256373563666e503557..."
//
// verify, err := bcrypt.Verify(hash, "password")
// if err != nil {
// fmt.Println(err)
// }
// fmt.Println(verify) // true
// }
func Verify(hash string, plain string) (bool, error) {
if hash == "" || plain == "" {
return false, ErrEmptyField
}
deserialize := format.Deserialize(hash)
if !strings.HasPrefix(deserialize.ID, "bcrypt") {
return false, errors.New("hashed string is not a bcrypt instance")
}
decodedHash, err := hex.DecodeString(deserialize.Hash)
if err != nil {
return false, err
}
err = bcrypt.CompareHashAndPassword(decodedHash, []byte(plain))
if err != nil {
return false, nil
}
return true, nil
}