-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhash.go
129 lines (106 loc) · 2.95 KB
/
hash.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package utils
import (
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"math/big"
whirl "github.com/balacode/zr-whirl"
)
type (
Type int
Length int
Characters string
)
const (
GeneratePassword Type = iota
GenerateSalt
GenerateUsername
)
const (
UsernameCharacters Characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
SaltCharacters Characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/."
PasswordCharacters Characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@*()&"
)
const (
PasswordLength Length = 12
SaltLength Length = 22
UsernameLength Length = 20
)
// HashPass hashes a password using a Whirlpool hash.
// Passwords are presumed to be hashed.
func HashPass(password string) string {
var iter = 1000
var next string
for i := 0; i < iter; i++ {
next += password
tmp := whirl.HashOfBytes([]byte(next), []byte(""))
next = hex.EncodeToString(tmp)
}
return next
}
func GenerateRandomLength(length int, randomType Type) (string, error) {
if length < 6 || length > 40 {
return "", errors.New("length must be between 6 and 40")
}
switch randomType {
case GeneratePassword:
b, err := rangeLoop(PasswordCharacters, Length(length))
if err != nil {
return "", fmt.Errorf("error generating random password: %w", err)
}
return b, nil
case GenerateSalt:
b, err := rangeLoop(SaltCharacters, Length(length))
if err != nil {
return "", fmt.Errorf("error generating random salt: %w", err)
}
return "$2a$06$" + b, nil
case GenerateUsername:
b, err := rangeLoop(UsernameCharacters, Length(length))
if err != nil {
return "", fmt.Errorf("error generating random username: %w", err)
}
return b, nil
default:
return "", fmt.Errorf("invalid type: %d", randomType)
}
}
// GenerateRandom generates a random string for either password or salt
func GenerateRandom(randomType Type) (string, error) {
switch randomType {
case GeneratePassword:
b, err := rangeLoop(PasswordCharacters, PasswordLength)
if err != nil {
return "", fmt.Errorf("error generating random password: %w", err)
}
return b, nil
case GenerateSalt:
b, err := rangeLoop(SaltCharacters, SaltLength)
if err != nil {
return "", fmt.Errorf("error generating random salt: %w", err)
}
return "$2a$06$" + b, nil
case GenerateUsername:
b, err := rangeLoop(UsernameCharacters, UsernameLength)
if err != nil {
return "", fmt.Errorf("error generating random username: %w", err)
}
return b, nil
default:
return "", fmt.Errorf("invalid type: %d", randomType)
}
}
// rangeLoop creates the random string that will be used
func rangeLoop(characters Characters, randomLength Length) (string, error) {
bytes := make([]byte, randomLength)
length := big.NewInt(int64(len(characters)))
for i := range bytes {
randInt, err := rand.Int(rand.Reader, length)
if err != nil {
return "", err
}
bytes[i] = characters[randInt.Int64()]
}
return string(bytes), nil
}