2022-06-24 23:09:46 +04:00
|
|
|
package captcha
|
|
|
|
|
|
|
|
import (
|
2022-10-20 22:55:37 +04:00
|
|
|
"crypto/rand"
|
2022-06-24 23:09:46 +04:00
|
|
|
"crypto/sha256"
|
|
|
|
"encoding/base64"
|
|
|
|
"image"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2022-10-20 22:55:37 +04:00
|
|
|
const DefaultExpiredScanInterval = 60 * time.Second
|
2022-06-27 01:02:24 +04:00
|
|
|
|
2022-10-20 22:55:37 +04:00
|
|
|
// ID is a CAPTCHA identifier.
|
2022-06-27 00:26:03 +04:00
|
|
|
type ID string
|
|
|
|
|
2022-10-20 22:55:37 +04:00
|
|
|
// 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.
|
2022-06-27 01:02:24 +04:00
|
|
|
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))
|
2022-10-20 22:55:37 +04:00
|
|
|
randData := make([]byte, 32)
|
|
|
|
rand.Read(randData)
|
|
|
|
idHash.Write(randData)
|
2022-06-27 01:02:24 +04:00
|
|
|
|
|
|
|
return ID(base64.RawURLEncoding.EncodeToString(idHash.Sum(nil)))
|
|
|
|
}
|
2022-06-24 23:09:46 +04:00
|
|
|
|
2022-10-20 22:55:37 +04:00
|
|
|
// CaptchaDB interface with all necessary methods.
|
2022-07-30 15:39:19 +04:00
|
|
|
type CaptchaDB interface {
|
2022-08-19 02:15:34 +04:00
|
|
|
New(data string, captcha Captcha) (Captcha, ID)
|
2022-06-26 21:28:22 +04:00
|
|
|
GetExpiry() time.Duration
|
2022-10-20 22:55:37 +04:00
|
|
|
SetExpiry(expiry time.Duration)
|
2022-10-20 23:50:42 +04:00
|
|
|
Image(id ID, style string) *image.Image
|
|
|
|
Solve(id ID, answer Answer) bool
|
|
|
|
IsSolved(id ID) bool
|
|
|
|
Remove(id ID)
|
2022-08-28 23:27:54 +04:00
|
|
|
}
|