123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- package otp
- import (
- "github.com/boombuler/barcode"
- "github.com/boombuler/barcode/qr"
- "crypto/md5"
- "crypto/sha1"
- "crypto/sha256"
- "crypto/sha512"
- "errors"
- "fmt"
- "hash"
- "image"
- "net/url"
- "strings"
- )
- var ErrValidateSecretInvalidBase32 = errors.New("Decoding of secret as base32 failed.")
- var ErrValidateInputInvalidLength = errors.New("Input length unexpected")
- var ErrGenerateMissingIssuer = errors.New("Issuer must be set")
- var ErrGenerateMissingAccountName = errors.New("AccountName must be set")
- type Key struct {
- orig string
- url *url.URL
- }
- func NewKeyFromURL(orig string) (*Key, error) {
- u, err := url.Parse(orig)
- if err != nil {
- return nil, err
- }
- return &Key{
- orig: orig,
- url: u,
- }, nil
- }
- func (k *Key) String() string {
- return k.orig
- }
- func (k *Key) Image(width int, height int) (image.Image, error) {
- b, err := qr.Encode(k.orig, qr.M, qr.Auto)
- if err != nil {
- return nil, err
- }
- b, err = barcode.Scale(b, width, height)
- if err != nil {
- return nil, err
- }
- return b, nil
- }
- func (k *Key) Type() string {
- return k.url.Host
- }
- func (k *Key) Issuer() string {
- q := k.url.Query()
- issuer := q.Get("issuer")
- if issuer != "" {
- return issuer
- }
- p := strings.TrimPrefix(k.url.Path, "/")
- i := strings.Index(p, ":")
- if i == -1 {
- return ""
- }
- return p[:i]
- }
- func (k *Key) AccountName() string {
- p := strings.TrimPrefix(k.url.Path, "/")
- i := strings.Index(p, ":")
- if i == -1 {
- return p
- }
- return p[i+1:]
- }
- func (k *Key) Secret() string {
- q := k.url.Query()
- return q.Get("secret")
- }
- type Algorithm int
- const (
- AlgorithmSHA1 Algorithm = iota
- AlgorithmSHA256
- AlgorithmSHA512
- AlgorithmMD5
- )
- func (a Algorithm) String() string {
- switch a {
- case AlgorithmSHA1:
- return "SHA1"
- case AlgorithmSHA256:
- return "SHA256"
- case AlgorithmSHA512:
- return "SHA512"
- case AlgorithmMD5:
- return "MD5"
- }
- panic("unreached")
- }
- func (a Algorithm) Hash() hash.Hash {
- switch a {
- case AlgorithmSHA1:
- return sha1.New()
- case AlgorithmSHA256:
- return sha256.New()
- case AlgorithmSHA512:
- return sha512.New()
- case AlgorithmMD5:
- return md5.New()
- }
- panic("unreached")
- }
- type Digits int
- const (
- DigitsSix Digits = 6
- DigitsEight Digits = 8
- )
- func (d Digits) Format(in int32) string {
- f := fmt.Sprintf("%%0%dd", d)
- return fmt.Sprintf(f, in)
- }
- func (d Digits) Length() int {
- return int(d)
- }
- func (d Digits) String() string {
- return fmt.Sprintf("%d", d)
- }
|