mirror of
https://github.com/Awuqing/BackupX.git
synced 2026-05-06 20:02:41 +08:00
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.
50 lines
1.0 KiB
Go
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
|
|
}
|