package authenticator import ( "encoding/hex" "fmt" "strconv" "strings" ) // EncodeSecretData encodes the "\t\t\t" string // that the original WinAuth config uses inside . func (b *Base) EncodeSecretData() string { return fmt.Sprintf( "%s\t%d\t%s\t%d", strings.ToUpper(hex.EncodeToString(b.SecretKey)), b.CodeDigits, b.HMACType.String(), b.Period, ) } // DecodeSecretData parses the value produced by EncodeSecretData (and // optionally a "|"-suffixed payload for HOTP subclasses). func (b *Base) DecodeSecretData(value string) error { if value == "" { b.SecretKey = nil return nil } head := strings.SplitN(value, "|", 2)[0] parts := strings.Split(head, "\t") if len(parts) == 0 { return fmt.Errorf("authenticator: empty secret data") } raw, err := hex.DecodeString(parts[0]) if err != nil { return fmt.Errorf("authenticator: bad secret hex: %w", err) } b.SecretKey = raw if len(parts) > 1 { if d, err := strconv.Atoi(parts[1]); err == nil { b.CodeDigits = d } } if len(parts) > 2 { switch strings.ToUpper(parts[2]) { case "SHA256": b.HMACType = HMACSHA256 case "SHA512": b.HMACType = HMACSHA512 default: b.HMACType = HMACSHA1 } } if len(parts) > 3 { if p, err := strconv.Atoi(parts[3]); err == nil && p > 0 { b.Period = p } } return nil }