Golang中使用哈希密码作为键值存储的键
Golang中使用哈希密码作为键值存储的键 我有一个应用程序需要在键值存储中存储一些用户信息。我考虑使用用户的单向加密密码作为键,但我尝试的不同方法每次加密密码时都会生成不同的哈希值。
我最初考虑使用bcrypt,但我不想通过CompareHashAndPassword()遍历每个键来查找匹配项。
也许我从错误的角度处理这个问题,但是否有一种加密密码的方法,使得生成的哈希字符串始终保持相同?
谢谢,
Rob
2 回复
也许这个方法可行,它似乎每次对相同的密码都返回相同的字符串:
func main() {
fmt.Println("hello world")
}
或者有没有更好的方法来实现这个?
谢谢
更多关于Golang中使用哈希密码作为键值存储的键的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中,如果你需要一个密码的哈希值始终相同以便作为键值存储的键,那么你需要的不是密码哈希,而是密码的消息摘要或密钥派生函数。
密码哈希算法(如bcrypt)设计上会在每次调用时生成不同的哈希值,这是出于安全考虑——它们会随机生成盐值来防止彩虹表攻击。但作为存储键,你需要的是确定性输出。
以下是几种解决方案:
方案1:使用HMAC(推荐)
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
)
func generateStableKey(password string, secretKey []byte) string {
h := hmac.New(sha256.New, secretKey)
h.Write([]byte(password))
return hex.EncodeToString(h.Sum(nil))
}
func main() {
secretKey := []byte("your-secret-key-here")
password := "userpassword123"
key1 := generateStableKey(password, secretKey)
key2 := generateStableKey(password, secretKey)
fmt.Printf("Key 1: %s\n", key1)
fmt.Printf("Key 2: %s\n", key2)
fmt.Printf("Keys match: %t\n", key1 == key2)
}
方案2:使用固定盐值的PBKDF2
package main
import (
"crypto/sha256"
"encoding/hex"
"golang.org/x/crypto/pbkdf2"
)
func generateStableKey(password string) string {
salt := []byte("fixed-salt-for-keys") // 使用固定盐值
key := pbkdf2.Key([]byte(password), salt, 4096, 32, sha256.New)
return hex.EncodeToString(key)
}
func main() {
password := "userpassword123"
key1 := generateStableKey(password)
key2 := generateStableKey(password)
fmt.Printf("Key 1: %s\n", key1)
fmt.Printf("Key 2: %s\n", key2)
}
方案3:简单的SHA256(如果安全性要求不高)
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
)
func generateStableKey(password string) string {
hash := sha256.Sum256([]byte(password))
return hex.EncodeToString(hash[:])
}
func main() {
password := "userpassword123"
key1 := generateStableKey(password)
key2 := generateStableKey(password)
fmt.Printf("Key 1: %s\n", key1)
fmt.Printf("Key 2: %s\n", key2)
fmt.Printf("Keys match: %t\n", key1 == key2)
}
完整的使用示例
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
)
type UserStore struct {
data map[string]interface{}
secretKey []byte
}
func NewUserStore(secretKey string) *UserStore {
return &UserStore{
data: make(map[string]interface{}),
secretKey: []byte(secretKey),
}
}
func (us *UserStore) generateKey(password string) string {
h := hmac.New(sha256.New, us.secretKey)
h.Write([]byte(password))
return hex.EncodeToString(h.Sum(nil))
}
func (us *UserStore) StoreUserInfo(password string, userInfo interface{}) {
key := us.generateKey(password)
us.data[key] = userInfo
fmt.Printf("Stored user info with key: %s\n", key)
}
func (us *UserStore) GetUserInfo(password string) interface{} {
key := us.generateKey(password)
return us.data[key]
}
func main() {
store := NewUserStore("my-secret-app-key")
password := "user123password"
userInfo := map[string]string{
"name": "John Doe",
"email": "john@example.com",
}
// 存储用户信息
store.StoreUserInfo(password, userInfo)
// 检索用户信息
retrievedInfo := store.GetUserInfo(password)
fmt.Printf("Retrieved: %v\n", retrievedInfo)
}
重要安全提醒:虽然这些方法能生成确定性哈希作为键,但请注意原始密码仍然可能被暴力破解。在生产环境中,建议:
- 使用足够复杂的密钥(HMAC方案)
- 考虑结合其他用户标识符(如用户名)来创建复合键
- 确保存储系统本身的安全性
HMAC方案是最推荐的,因为它提供了更好的安全性,同时保持了作为键所需的确定性特性。

