func (ya *YubiAuth) HttpsVerifyCertificate(verifyCertificate bool) {
	ya.use.Lock()
	defer ya.use.Unlock()
	ya.verifyCertificate = verifyCertificate
	ya.buildWorkers()
}
Enable or disable https certificate verification
Disable this at your own risk.
package yubigo
import (
	"bufio"
	"context"
	"crypto/hmac"
	"crypto/sha1"
	"crypto/tls"
	"encoding/base64"
	"errors"
	"fmt"
	"io"
	"log"
	"math/rand"
	"net/http"
	"regexp"
	"sort"
	"strings"
	"sync"
	"time"
)
var (
	dvorakToQwerty = strings.NewReplacer(
		"j", "c", "x", "b", "e", "d", ".", "e", "u", "f", "i", "g", "d", "h", "c", "i",
		"h", "j", "t", "k", "n", "l", "b", "n", "p", "r", "y", "t", "g", "u", "k", "v",
		"J", "C", "X", "B", "E", "D", ".", "E", "U", "F", "I", "G", "D", "H", "C", "I",
		"H", "J", "T", "K", "N", "L", "B", "N", "P", "R", "Y", "T", "G", "U", "K", "V")
	matchDvorak     = regexp.MustCompile(`^[jxe.uidchtnbpygkJXE.UIDCHTNBPYGK]{32,48}$`)
	matchQwerty     = regexp.MustCompile(`^[cbdefghijklnrtuvCBDEFGHIJKLNRTUV]{32,48}$`)
	signatureUrlFix = regexp.MustCompile(`\+`)
)
var HTTPClient *http.Client = nil
func ParseOTP(otp string) (prefix string, ciphertext string, err error) {
	if len(otp) < 32 || len(otp) > 48 {
		err = errors.New("OTP has wrong length.")
		return
	}
	if matchDvorak.MatchString(otp) {
		otp = dvorakToQwerty.Replace(otp)
	}
	if !matchQwerty.MatchString(otp) {
		err = errors.New("Given string is not a valid Yubikey OTP. It contains invalid characters and/or the length is wrong.")
		return
	}
	l := len(otp)
	prefix = otp[0 : l-32]
	ciphertext = otp[l-32 : l]
	return
}
type YubiAuth struct {
	id                string
	key               []byte
	apiServerList     []string
	protocol          string
	verifyCertificate bool
	workers           []*verifyWorker
	use               sync.Mutex
	debug             bool
}
type verifyWorker struct {
	ya        *YubiAuth          
	id        int                
	client    *http.Client       
	apiServer string             
	work      chan *workRequest  
	stop      chan bool          
}
type workRequest struct {
	ctx context.Context
	paramString *string
	resultChan  chan *workResult
}
type workResult struct {
	response     *http.Response
	requestQuery string
	err          error  
}
func (vw *verifyWorker) process() {
	if vw.ya.debug {
		log.Printf("worker[%d]: Started.\n", vw.id)
	}
	for {
		select {
		case w := <-vw.work:
			url := vw.ya.protocol + vw.apiServer + *w.paramString
			if vw.ya.debug {
				log.Printf("worker[%d]: Have work. Requesting: %s\n", vw.id, url)
			}
			request, err := http.NewRequest("GET", url, nil)
			if err != nil {
				w.resultChan <- &workResult{
					response:     nil,
					requestQuery: url,
					err:          fmt.Errorf("Could not create http request. Error: %s\n", err),
				}
				continue
			}
			request.Header.Add("User-Agent", "github.com/GeertJohan/yubigo")
			request = request.WithContext(w.ctx)
			response, err := vw.client.Do(request)
			if err != nil {
				if w.ctx.Err() == context.Canceled {
					continue
				}
				w.resultChan <- &workResult{
					response:     nil,
					requestQuery: url,
					err:          fmt.Errorf("Http client error: %s\n", err),
				}
				if vw.ya.debug {
					log.Printf("worker[%d]: Http client error: %s", vw.id, err)
				}
				continue
			}
			if vw.ya.debug {
				log.Printf("worker[%d] Received result from api server. Sending on channel.", vw.id)
			}
			w.resultChan <- &workResult{
				response:     response,
				requestQuery: url,
				err:          nil,
			}
			continue
		case <-vw.stop:
			if vw.ya.debug {
				log.Printf("worker[%d]: received stop signal.\n", vw.id)
			}
			return
		}
	}
}
func NewYubiAuth(id string, key string) (auth *YubiAuth, err error) {
	return NewYubiAuthDebug(id, key, false)
}
func NewYubiAuthDebug(id string, key string, debug bool) (auth *YubiAuth, err error) {
	keyBytes, err := base64.StdEncoding.DecodeString(key)
	if err != nil {
		err = fmt.Errorf("Given key seems to be invalid. Could not base64_decode. Error: %s\n", err)
		return
	}
	if debug {
		log.Printf("NewYubiAuthDebug: Given key is base64 decodable. Creating new YubiAuth instance with api id '%s'.\n", id)
	}
	auth = &YubiAuth{
		id:  id,
		key: keyBytes,
		apiServerList: []string{"api.yubico.com/wsapi/2.0/verify",
			"api2.yubico.com/wsapi/2.0/verify",
			"api3.yubico.com/wsapi/2.0/verify",
			"api4.yubico.com/wsapi/2.0/verify",
			"api5.yubico.com/wsapi/2.0/verify"},
		protocol:          "https://",
		verifyCertificate: true,
		debug: debug,
	}
	if debug {
		log.Printf("NewYubiAuthDebug: Using yubico web servers: %#v\n", auth.apiServerList)
		log.Println("NewYubiAuthDebug: Going to build workers.")
	}
	auth.buildWorkers()
	return
}
func (ya *YubiAuth) buildWorkers() {
	tlsConfig := &tls.Config{}
	if !ya.verifyCertificate {
		tlsConfig.InsecureSkipVerify = true
	}
	for _, worker := range ya.workers {
		worker.stop <- true
	}
	ya.workers = make([]*verifyWorker, 0, len(ya.apiServerList))
	for id, apiServer := range ya.apiServerList {
		worker := &verifyWorker{
			ya:        ya,
			id:        id,
			apiServer: apiServer + "?",
			work:      make(chan *workRequest),
			stop:      make(chan bool),
		}
		if HTTPClient == nil {
			worker.client = &http.Client{
				Transport: &http.Transport{
					TLSClientConfig: tlsConfig,
				},
			}
		} else {
			worker.client = HTTPClient
		}
		ya.workers = append(ya.workers, worker)
		go worker.process()
	}
}
func (ya *YubiAuth) SetApiServerList(urls ...string) {
	ya.use.Lock()
	defer ya.use.Unlock()
	ya.apiServerList = urls
	ya.buildWorkers()
}
func (ya *YubiAuth) GetApiServerList() []string {
	return ya.apiServerList
}
func (ya *YubiAuth) UseHttps(useHttps bool) {
	ya.use.Lock()
	defer ya.use.Unlock()
	if useHttps {
		ya.protocol = "https://"
	} else {
		ya.protocol = "http://"
	}
}