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)
}

重要安全提醒:虽然这些方法能生成确定性哈希作为键,但请注意原始密码仍然可能被暴力破解。在生产环境中,建议:

  1. 使用足够复杂的密钥(HMAC方案)
  2. 考虑结合其他用户标识符(如用户名)来创建复合键
  3. 确保存储系统本身的安全性

HMAC方案是最推荐的,因为它提供了更好的安全性,同时保持了作为键所需的确定性特性。

回到顶部