...
1
2
3
4
5
6
7
8
9
10
11
12
13
14 package timestampcache
15
16 import (
17 "context"
18 "crypto/sha256"
19 "fmt"
20 "log"
21 "time"
22
23 "github.com/bradfitz/gomemcache/memcache"
24 "github.com/pkg/errors"
25 "github.com/sassoftware/relic/lib/pkcs7"
26 "github.com/sassoftware/relic/lib/pkcs9"
27 )
28
29 const (
30 memcacheTimeout = 1 * time.Second
31 memcacheExpiry = 7 * 24 * time.Hour
32 )
33
34 type timestampCache struct {
35 Timestamper pkcs9.Timestamper
36 Memcache *memcache.Client
37 }
38
39 func New(t pkcs9.Timestamper, servers []string) (pkcs9.Timestamper, error) {
40 selector := new(memcache.ServerList)
41 if err := selector.SetServers(servers...); err != nil {
42 return nil, errors.Wrap(err, "parsing memcache servers")
43 }
44 mc := memcache.NewFromSelector(selector)
45 mc.Timeout = memcacheTimeout
46 return ×tampCache{t, mc}, nil
47 }
48
49 func (c *timestampCache) Timestamp(ctx context.Context, req *pkcs9.Request) (*pkcs7.ContentInfoSignedData, error) {
50 key := cacheKey(req)
51 item, err := c.Memcache.Get(key)
52 if err == nil {
53 token, err := pkcs7.Unmarshal(item.Value)
54 if err == nil {
55 return token, nil
56 }
57 log.Printf("warning: failed to parse cached value for timestamp with key %s: %s", key, err)
58
59 }
60 token, err := c.Timestamper.Timestamp(ctx, req)
61 if err == nil {
62 blob, err := token.Marshal()
63 if err != nil {
64 return nil, err
65 }
66 if err := c.Memcache.Set(&memcache.Item{
67 Key: key,
68 Value: blob,
69 Expiration: int32(memcacheExpiry / time.Second),
70 }); err != nil {
71 log.Printf("warning: failed to save cached timestamp value: %s", err)
72 }
73 }
74 return token, err
75 }
76
77 func cacheKey(req *pkcs9.Request) string {
78 d := sha256.New()
79 d.Write(req.EncryptedDigest)
80 prefix := "pkcs9"
81 if req.Legacy {
82 prefix = "msft"
83 }
84 return fmt.Sprintf("%s-%d-%x", prefix, req.Hash, d.Sum(nil))
85 }
86
View as plain text