tokens.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. package dht
  2. import (
  3. "crypto/sha1"
  4. "encoding/binary"
  5. "time"
  6. "github.com/bradfitz/iter"
  7. )
  8. // Manages creation and validation of tokens issued to querying nodes.
  9. type tokenServer struct {
  10. // Something only we know that peers can't guess, so they can't deduce valid tokens.
  11. secret []byte
  12. // How long between token changes.
  13. interval time.Duration
  14. // How many intervals may pass between the current interval, and one used to generate a token before it is invalid.
  15. maxIntervalDelta int
  16. timeNow func() time.Time
  17. }
  18. func (me tokenServer) CreateToken(addr Addr) string {
  19. return me.createToken(addr, me.getTimeNow())
  20. }
  21. func (me tokenServer) createToken(addr Addr, t time.Time) string {
  22. h := sha1.New()
  23. ip := addr.IP().To16()
  24. if len(ip) != 16 {
  25. panic(ip)
  26. }
  27. h.Write(ip)
  28. ti := t.UnixNano() / int64(me.interval)
  29. var b [8]byte
  30. binary.BigEndian.PutUint64(b[:], uint64(ti))
  31. h.Write(b[:])
  32. h.Write(me.secret)
  33. return string(h.Sum(nil))
  34. }
  35. func (me *tokenServer) ValidToken(token string, addr Addr) bool {
  36. t := me.getTimeNow()
  37. for range iter.N(me.maxIntervalDelta + 1) {
  38. if me.createToken(addr, t) == token {
  39. return true
  40. }
  41. t = t.Add(-me.interval)
  42. }
  43. return false
  44. }
  45. func (me *tokenServer) getTimeNow() time.Time {
  46. if me.timeNow == nil {
  47. return time.Now()
  48. }
  49. return me.timeNow()
  50. }