-
Notifications
You must be signed in to change notification settings - Fork 0
/
hasher.go
142 lines (121 loc) · 3.53 KB
/
hasher.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
130
131
132
133
134
135
136
137
138
139
140
141
142
package utils
import (
"crypto/rand"
"crypto/sha512"
"encoding/base64"
"fmt"
"github.com/sirupsen/logrus"
)
const DefaultSaltSize = 512
type hasher struct {
Secret string `json:"secret" bson:"secret"`
}
// type IHasher interface {
// generateSalt() (salt []byte, err error)
// Hash(password string, salt []byte) (hashedPassword string, err error)
// IsMatch(hashedPassword, password string, salt []byte) bool
// }
func NewHasher() *hasher {
return new(hasher)
}
func (h *hasher) LoadSecret(secret string) *hasher {
h.Secret = secret
return h
}
func (h *hasher) Hash(value string) (hashedPassword string, err error) {
// Create sha-512 hasher
var sha512Hasher = sha512.New()
// Password + Secret
passwordWithSalt := append([]byte(value), []byte(h.Secret)...)
// Hashing
if _, err = sha512Hasher.Write(passwordWithSalt); err != nil {
return "", fmt.Errorf("error hashing value: %v", err)
}
// Get hashed SHA-512 value
var byteHashedPassword = sha512Hasher.Sum(nil)
return base64.URLEncoding.EncodeToString(byteHashedPassword), nil
}
func (h *hasher) IsMatch(currentValue string, hashedValue string) bool {
var currentHash, err = h.Hash(currentValue)
if err != nil {
logrus.Errorf("can't hash propperly: %v", err)
return false
}
return hashedValue == currentHash
}
func (h *hasher) GenerateSecret(length ...int) (secret string, err error) {
if length == nil {
length[0] = DefaultSaltSize
}
raw := make([]byte, length[0])
// create salt
if _, err = rand.Read(raw[:]); err != nil {
return "", fmt.Errorf("can't create salt: %v", err)
}
// encode b64
secret = base64.URLEncoding.EncodeToString(raw)
return
}
// without salt
// func (h *hasher) Encrypt(stringToEncrypt string, keyString string) (encryptedString string) {
//
// // Since the key is in string, we need to convert decode it to bytes
// key, _ := hex.DecodeString(keyString)
// plaintext := []byte(stringToEncrypt)
//
// // Create a new Cipher Block from the key
// block, err := aes.NewCipher(key)
// if err != nil {
// panic(err.Error())
// }
//
// // Create a new GCM - https://en.wikipedia.org/wiki/Galois/Counter_Mode
// // https://golang.org/pkg/crypto/cipher/#NewGCM
// aesGCM, err := cipher.NewGCM(block)
// if err != nil {
// panic(err.Error())
// }
//
// // Create a nonce. Nonce should be from GCM
// nonce := make([]byte, aesGCM.NonceSize())
// if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
// panic(err.Error())
// }
//
// // Encrypt the data using aesGCM.Seal
// // Since we don't want to save the nonce somewhere else in this case, we add it as a prefix to the encrypted data. The first nonce argument in Seal is the prefix.
// ciphertext := aesGCM.Seal(nonce, nonce, plaintext, nil)
// return fmt.Sprintf("%x", ciphertext)
//
// }
// func (h *hasher) Decrypt(encryptedString string, keyString string) (decryptedString string) {
//
// key, _ := hex.DecodeString(keyString)
// enc, _ := hex.DecodeString(encryptedString)
//
// // Create a new Cipher Block from the key
// block, err := aes.NewCipher(key)
// if err != nil {
// panic(err.Error())
// }
//
// // Create a new GCM
// aesGCM, err := cipher.NewGCM(block)
// if err != nil {
// panic(err.Error())
// }
//
// // Get the nonce size
// nonceSize := aesGCM.NonceSize()
//
// // Extract the nonce from the encrypted data
// nonce, ciphertext := enc[:nonceSize], enc[nonceSize:]
//
// // Decrypt the data
// plaintext, err := aesGCM.Open(nil, nonce, ciphertext, nil)
// if err != nil {
// panic(err.Error())
// }
//
// return fmt.Sprintf("%s", plaintext)
// }