76 lines
1.4 KiB
Go
76 lines
1.4 KiB
Go
// Copyright (C) 2019 Marius Schellenberger
|
|
|
|
package otp
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
"errors"
|
|
"github.com/pquerna/otp"
|
|
"github.com/pquerna/otp/totp"
|
|
"html/template"
|
|
"image/png"
|
|
)
|
|
|
|
const size = 200
|
|
|
|
func base64Image(key *otp.Key) (data template.URL, err error) {
|
|
var buf bytes.Buffer
|
|
img, err := key.Image(size, size)
|
|
if err != nil {
|
|
err = errors.New("otp: " + err.Error())
|
|
return
|
|
}
|
|
err = png.Encode(&buf, img)
|
|
if err != nil {
|
|
err = errors.New("otp: " + err.Error())
|
|
return
|
|
}
|
|
data = template.URL("data:image/png;base64," + base64.StdEncoding.EncodeToString(buf.Bytes()))
|
|
return
|
|
}
|
|
|
|
type Request struct {
|
|
Username string
|
|
Image template.URL
|
|
Secret string
|
|
URL string
|
|
}
|
|
|
|
func New(username string) (req Request, err error) {
|
|
key, err := totp.Generate(totp.GenerateOpts{
|
|
Issuer: "gowiki",
|
|
AccountName: username,
|
|
})
|
|
if err != nil {
|
|
return
|
|
}
|
|
data, err := base64Image(key)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return Request{
|
|
Username: username,
|
|
Image: data,
|
|
Secret: key.Secret(),
|
|
URL: key.URL(),
|
|
}, nil
|
|
}
|
|
|
|
func Validate(pin, secret string) bool {
|
|
if secret == "" {
|
|
return true
|
|
}
|
|
return totp.Validate(pin, secret)
|
|
}
|
|
|
|
func ImageSecretFromURL(url string) (data template.URL, secret string, err error) {
|
|
key, err := otp.NewKeyFromURL(url)
|
|
if err != nil {
|
|
err = errors.New("otp: " + err.Error())
|
|
return
|
|
}
|
|
secret = key.Secret()
|
|
data, err = base64Image(key)
|
|
return
|
|
}
|