Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -2,6 +2,10 @@ package services
|
||||
|
||||
import (
|
||||
"bssapp-backend/models"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
@@ -16,7 +20,6 @@ func CheckPasswordWithLegacy(user *models.User, plain string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
plain = strings.TrimSpace(plain)
|
||||
if plain == "" {
|
||||
return false
|
||||
}
|
||||
@@ -28,11 +31,100 @@ func CheckPasswordWithLegacy(user *models.User, plain string) bool {
|
||||
|
||||
// 1️⃣ bcrypt hash mi?
|
||||
if isBcryptHash(stored) {
|
||||
return bcrypt.CompareHashAndPassword([]byte(stored), []byte(plain)) == nil
|
||||
candidates := make([]string, 0, 10)
|
||||
seen := map[string]struct{}{}
|
||||
add := func(v string) {
|
||||
if v == "" {
|
||||
return
|
||||
}
|
||||
if _, ok := seen[v]; ok {
|
||||
return
|
||||
}
|
||||
seen[v] = struct{}{}
|
||||
candidates = append(candidates, v)
|
||||
}
|
||||
|
||||
add(plain)
|
||||
trimmed := strings.TrimSpace(plain)
|
||||
add(trimmed)
|
||||
|
||||
bases := append([]string(nil), candidates...)
|
||||
for _, base := range bases {
|
||||
md5Sum := md5.Sum([]byte(base))
|
||||
md5Hex := hex.EncodeToString(md5Sum[:])
|
||||
add(md5Hex)
|
||||
add(strings.ToUpper(md5Hex))
|
||||
|
||||
sha1Sum := sha1.Sum([]byte(base))
|
||||
sha1Hex := hex.EncodeToString(sha1Sum[:])
|
||||
add(sha1Hex)
|
||||
add(strings.ToUpper(sha1Hex))
|
||||
}
|
||||
|
||||
var lastErr error
|
||||
for _, candidate := range candidates {
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(stored), []byte(candidate)); err == nil {
|
||||
return true
|
||||
} else {
|
||||
lastErr = err
|
||||
}
|
||||
if encoded, ok := encodeLegacySingleByte(candidate); ok {
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(stored), encoded); err == nil {
|
||||
return true
|
||||
} else {
|
||||
lastErr = err
|
||||
}
|
||||
}
|
||||
}
|
||||
if lastErr != nil {
|
||||
log.Printf(
|
||||
"LEGACY BCRYPT MISMATCH stored_len=%d candidates=%d last_err=%v",
|
||||
len(stored),
|
||||
len(candidates),
|
||||
lastErr,
|
||||
)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 2️⃣ TAM LEGACY — düz metin (eski kayıtlar)
|
||||
return stored == plain
|
||||
if stored == plain {
|
||||
return true
|
||||
}
|
||||
trimmed := strings.TrimSpace(plain)
|
||||
if trimmed != plain && trimmed != "" && stored == trimmed {
|
||||
return true
|
||||
}
|
||||
|
||||
// 3️⃣ Legacy hash variants seen in old dfusr.upass data.
|
||||
if isHexDigest(stored, 32) {
|
||||
sumRaw := md5.Sum([]byte(plain))
|
||||
if strings.EqualFold(stored, hex.EncodeToString(sumRaw[:])) {
|
||||
return true
|
||||
}
|
||||
if trimmed != plain && trimmed != "" {
|
||||
sumTrim := md5.Sum([]byte(trimmed))
|
||||
if strings.EqualFold(stored, hex.EncodeToString(sumTrim[:])) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if isHexDigest(stored, 40) {
|
||||
sumRaw := sha1.Sum([]byte(plain))
|
||||
if strings.EqualFold(stored, hex.EncodeToString(sumRaw[:])) {
|
||||
return true
|
||||
}
|
||||
if trimmed != plain && trimmed != "" {
|
||||
sumTrim := sha1.Sum([]byte(trimmed))
|
||||
if strings.EqualFold(stored, hex.EncodeToString(sumTrim[:])) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func isBcryptHash(s string) bool {
|
||||
@@ -40,3 +132,46 @@ func isBcryptHash(s string) bool {
|
||||
strings.HasPrefix(s, "$2b$") ||
|
||||
strings.HasPrefix(s, "$2y$")
|
||||
}
|
||||
|
||||
func isHexDigest(s string, expectedLen int) bool {
|
||||
if len(s) != expectedLen {
|
||||
return false
|
||||
}
|
||||
for _, r := range s {
|
||||
if (r < '0' || r > '9') &&
|
||||
(r < 'a' || r > 'f') &&
|
||||
(r < 'A' || r > 'F') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// encodeLegacySingleByte converts text to a Turkish-compatible single-byte
|
||||
// representation (similar to Windows-1254 / ISO-8859-9) for legacy bcrypt data.
|
||||
func encodeLegacySingleByte(s string) ([]byte, bool) {
|
||||
out := make([]byte, 0, len(s))
|
||||
for _, r := range s {
|
||||
switch r {
|
||||
case 'Ğ':
|
||||
out = append(out, 0xD0)
|
||||
case 'ğ':
|
||||
out = append(out, 0xF0)
|
||||
case 'İ':
|
||||
out = append(out, 0xDD)
|
||||
case 'ı':
|
||||
out = append(out, 0xFD)
|
||||
case 'Ş':
|
||||
out = append(out, 0xDE)
|
||||
case 'ş':
|
||||
out = append(out, 0xFE)
|
||||
default:
|
||||
if r >= 0 && r <= 0xFF {
|
||||
out = append(out, byte(r))
|
||||
} else {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
}
|
||||
return out, true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user