package captcha import ( "crypto/rand" "crypto/sha256" "encoding/base64" "image" "strconv" "time" ) const DefaultExpiredScanInterval = 60 * time.Second // ID is a CAPTCHA identifier. type ID string // NewID generates an ID as a sha256 hash of additionalData (usually IP-address), // current time, answer and more, it adds a set of random bytes and encodes all // of it with base64 in raw URL variant. func NewID(additionalData string, answer Answer) ID { idHash := sha256.New() idHash.Write([]byte(additionalData)) idHash.Write([]byte(strconv.FormatInt(time.Now().UnixMicro(), 16))) idHash.Write([]byte(answer)) randData := make([]byte, 32) rand.Read(randData) idHash.Write(randData) return ID(base64.RawURLEncoding.EncodeToString(idHash.Sum(nil))) } // CaptchaDB interface with all necessary methods. type CaptchaDB interface { New(data string, captcha Captcha) (Captcha, ID) GetExpiry() time.Duration SetExpiry(expiry time.Duration) Image(id ID, style string) *image.Image Solve(id ID, answer Answer) bool IsSolved(id ID) bool Remove(id ID) }