// Copyright 2026 Rose Hogenson // // This file is part of roseh.moe. // // roseh.moe is free software: you can redistribute it and/or modify it // under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // roseh.moe is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public // License along with roseh.moe. If not, // see . package main import ( "encoding/base32" "encoding/base64" "encoding/xml" "flag" "fmt" "os" "github.com/skip2/go-qrcode" ) func run() error { args := flag.Args() if len(args) != 1 { return fmt.Errorf("usage: auth ") } fileBytes, err := os.ReadFile(args[0]) if err != nil { return err } var config struct { AuthKey string `xml:",attr"` } if err := xml.Unmarshal(fileBytes, &config); err != nil { return err } if config.AuthKey == "" { return fmt.Errorf("%s: missing AuthKey", args[0]) } authKey, err := base64.StdEncoding.DecodeString(config.AuthKey) if err != nil { return err } qrCode, err := qrcode.New(fmt.Sprintf("otpauth://totp/roseh.moe:rose?secret=%s&issuer=roseh.moe", base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(authKey)), qrcode.Medium) if err != nil { return err } fmt.Print(qrCode.ToSmallString(false)) return nil } func main() { flag.Parse() if err := run(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } }