如何使用Go实现LDAP Salted MD5密码的验证功能
如何使用Go验证明文密码与加盐MD5(LDAP SMD5)密码是否一致?
LDAP的加盐MD5(SMD5)密码格式为{SMD5}<Base64编码内容>,其中Base64解码后的字节序列包含两部分:前16字节是MD5(明文密码+盐)的哈希值,剩余部分是随机生成的盐(通常为8字节)。验证的核心逻辑是用明文密码拼接盐重新计算MD5哈希,再与存储的哈希值对比。
Go实现代码
package main import ( "crypto/md5" "encoding/base64" "fmt" "strings" "bytes" ) // VerifySMD5 验证明文密码与LDAP SMD5格式的哈希是否匹配 func VerifySMD5(plainPassword, smd5Hash string) bool { // 校验并移除{SMD5}前缀 if !strings.HasPrefix(smd5Hash, "{SMD5}") { return false } encoded := strings.TrimPrefix(smd5Hash, "{SMD5}") // Base64解码原始内容 decoded, err := base64.StdEncoding.DecodeString(encoded) if err != nil { return false } // 校验解码后长度(至少包含16字节MD5哈希) if len(decoded) < 16 { return false } // 分离存储的哈希值与盐 storedHash := decoded[:16] salt := decoded[16:] // 计算明文密码+盐的MD5哈希 h := md5.New() h.Write([]byte(plainPassword)) h.Write(salt) calculatedHash := h.Sum(nil) // 对比两个哈希值(bytes.Equal比字符串对比更严谨) return bytes.Equal(calculatedHash, storedHash) } func main() { // 测试示例1 plainPass := "123456" smd5Pass := "{SMD5}991RjK3DQCT+ri/yxQB613Yuxdg=" fmt.Printf("验证结果1: %t\n", VerifySMD5(plainPass, smd5Pass)) // 输出 true // 测试示例2 smd5Pass2 := "{SMD5}ZmDHoIiZZG/weuCNkLj189sFoPM=" fmt.Printf("验证结果2: %t\n", VerifySMD5(plainPass, smd5Pass2)) // 输出 true }
代码说明
- 前缀校验:先确认输入的哈希字符串符合SMD5格式,移除前缀后获取核心的Base64编码内容。
- 解码处理:对编码内容进行Base64解码,解码失败则直接判定验证不通过。
- 内容拆分:按照SMD5的格式规则,从解码后的字节中分离出16字节的哈希值和剩余的盐。
- 哈希重算:使用Go标准库的
crypto/md5包,计算明文密码拼接盐后的哈希值。 - 哈希对比:用
bytes.Equal对比计算出的哈希与存储的哈希,确保字节序列完全一致。
内容的提问来源于stack exchange,提问作者CyberWon
相关产品推荐
相关产品推荐

