-
Notifications
You must be signed in to change notification settings - Fork 0
/
vey.go
105 lines (92 loc) · 2.17 KB
/
vey.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package vey
import "net/mail"
// vey implements Vey interface.
type vey struct {
digest Digester
cache Cache
store Store
}
func NewVey(digest Digester, cache Cache, store Store) Vey {
return vey{
digest: digest,
cache: cache,
store: store,
}
}
func validateEmail(email string) error {
_, err := mail.ParseAddress(email)
return err
}
func (k vey) GetKeys(email string) ([]PublicKey, error) {
if err := validateEmail(email); err != nil {
return nil, ErrInvalidEmail
}
digest := k.digest.Of(email)
return k.store.Get(digest)
}
func (k vey) BeginDelete(email string, publicKey PublicKey) ([]byte, error) {
if err := validateEmail(email); err != nil {
return nil, ErrInvalidEmail
}
digest := k.digest.Of(email)
token, err := NewToken()
if err != nil {
return nil, err
}
if err := k.cache.Set(token, Cached{
EmailDigest: digest,
PublicKey: publicKey,
}); err != nil {
return nil, err
}
return token, nil
}
func (k vey) CommitDelete(token []byte) error {
cached, err := k.cache.Get(token)
if err != nil {
return err
}
return k.store.Delete(cached.EmailDigest, cached.PublicKey)
}
func (k vey) BeginPut(email string, publicKey PublicKey) ([]byte, error) {
if err := validateEmail(email); err != nil {
return nil, ErrInvalidEmail
}
digest := k.digest.Of(email)
challenge, err := NewChallenge()
if err != nil {
return nil, err
}
if err := k.cache.Set(challenge, Cached{
EmailDigest: digest,
PublicKey: publicKey,
}); err != nil {
return nil, err
}
return challenge, nil
}
// CommitPut verifies the signature with the public key.
// CommitPut returns ErrVerifyFailed if the signature is invalid.
// The challenge is deleted whether or not verify succeeds.
func (k vey) CommitPut(challenge, signature []byte) (err error) {
var cached Cached
cached, err = k.cache.Get(challenge)
if err != nil {
return
}
// challenge is only valid once
defer func() {
er := k.cache.Del(challenge)
if err == nil {
err = er
}
}()
publicKey := cached.PublicKey
verifier := NewVerifier(publicKey.Type)
if !verifier.Verify(publicKey, signature, challenge) {
err = ErrVerifyFailed
return
}
err = k.store.Put(cached.EmailDigest, publicKey)
return
}