// =========================================== // 多班级版班级管理系统 - Go 后端 // // 开发者: Canglan // 联系方式: admin@sea-studio.top // 版权归属: Sea Network Technology Studio // 许可证: Apache License 2.0 // // 版权所有 © Sea Network Technology Studio // =========================================== package crypto import ( "crypto/md5" "crypto/rand" "crypto/sha1" "crypto/subtle" "encoding/hex" "fmt" "math/big" ) // HashPassword 密码哈希(与 Python 版完全兼容) // 算法: MD5(SHA1(password) + salt) // Python 参考: backend/utils/security.py -> sha1_md5_password() // 已知弱算法:MD5 和 SHA1 均不适合密码哈希场景,保留此实现仅为兼容 Python 版数据。 // 后续迁移计划:迁移到 bcrypt/scrypt/argon2,并提供兼容层逐步过渡。 func HashPassword(password string, salt string) string { // 第一层: SHA1(password) sha1Hash := sha1.Sum([]byte(password)) sha1Hex := hex.EncodeToString(sha1Hash[:]) // 加盐: SHA1_hex + salt salted := sha1Hex + salt // 第二层: MD5(salted) md5Hash := md5.Sum([]byte(salted)) return hex.EncodeToString(md5Hash[:]) } // VerifyPassword 验证密码(使用常量时间比较,防止时序攻击) func VerifyPassword(plainPassword, hashedPassword, salt string) bool { computed := HashPassword(plainPassword, salt) return subtle.ConstantTimeCompare([]byte(computed), []byte(hashedPassword)) == 1 } // GenerateRandomPassword 生成随机密码 // 与 Python 版 SecurityUtils.generate_random_password() 兼容 func GenerateRandomPassword(length int) (string, error) { alphabet := "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789" result := make([]byte, length) for i := range result { n, err := rand.Int(rand.Reader, big.NewInt(int64(len(alphabet)))) if err != nil { return "", fmt.Errorf("生成随机密码失败: %w", err) } result[i] = alphabet[n.Int64()] } return string(result), nil } // ValidatePasswordStrength 验证密码强度 // 要求: 大小写字母、数字、特殊符号至少包含 3 种,长度 6-20 func ValidatePasswordStrength(password string) (bool, string) { if len(password) < 6 { return false, "密码长度至少6位" } if len(password) > 20 { return false, "密码长度不能超过20位" } hasUpper := false hasLower := false hasDigit := false hasSpecial := false for _, c := range password { switch { case c >= 'A' && c <= 'Z': hasUpper = true case c >= 'a' && c <= 'z': hasLower = true case c >= '0' && c <= '9': hasDigit = true default: hasSpecial = true } } charTypes := 0 if hasUpper { charTypes++ } if hasLower { charTypes++ } if hasDigit { charTypes++ } if hasSpecial { charTypes++ } if charTypes < 3 { return false, "密码必须包含大写字母、小写字母、数字、特殊符号中的至少3种" } return true, "" }