Files
BackupX/server/internal/security/recovery_code.go
Wu Qing 5af5f97efb feat: add complete MFA support
Add complete MFA support with TOTP, recovery codes, WebAuthn, trusted-device cookie flow, and email/SMS OTP delivery via notification channels. Security follow-up: trusted device tokens are stored in HttpOnly cookies, and SMS OTP reuses the existing Webhook notifier to avoid introducing a new dynamic URL sink.
2026-04-25 22:14:50 +08:00

50 lines
1.0 KiB
Go

package security
import (
"crypto/rand"
"encoding/hex"
"fmt"
"strings"
"unicode"
)
const RecoveryCodeCount = 10
func GenerateRecoveryCodes(count int) ([]string, error) {
if count <= 0 {
count = RecoveryCodeCount
}
codes := make([]string, 0, count)
for i := 0; i < count; i++ {
raw := make([]byte, 8)
if _, err := rand.Read(raw); err != nil {
return nil, fmt.Errorf("generate recovery code: %w", err)
}
encoded := strings.ToUpper(hex.EncodeToString(raw))
codes = append(codes, encoded[0:4]+"-"+encoded[4:8]+"-"+encoded[8:12]+"-"+encoded[12:16])
}
return codes, nil
}
func NormalizeRecoveryCode(code string) string {
return strings.Map(func(r rune) rune {
if unicode.IsSpace(r) || r == '-' {
return -1
}
return unicode.ToUpper(r)
}, strings.TrimSpace(code))
}
func IsRecoveryCodeCandidate(code string) bool {
normalized := NormalizeRecoveryCode(code)
if len(normalized) != 16 {
return false
}
for _, r := range normalized {
if !('0' <= r && r <= '9') && !('A' <= r && r <= 'F') {
return false
}
}
return true
}