/
x509verify.go
109 lines (91 loc) · 2.09 KB
/
x509verify.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
106
107
108
109
package x509solution
import (
"crypto/x509"
"fmt"
"time"
"bitwormhole.com/starter/certificates"
"github.com/bitwormhole/starter/vlog"
)
type x509veri struct {
options certificates.VerifyOptions
chain certificates.Chain
roots certificates.RootManager
rawChain []*x509.Certificate
}
func (inst *x509veri) verify() error {
steps := make([]func() error, 0)
steps = append(steps, inst.prepare)
steps = append(steps, inst.verifyStandard)
for _, fn := range steps {
err := fn()
if err != nil {
return err
}
}
return nil
}
func (inst *x509veri) prepare() error {
src := inst.chain
dst := make([]*x509.Certificate, 0)
for ; src != nil; src = src.GetParent() {
cer, ok := src.GetCertificate().GetEntity().(*x509cert)
if !ok {
return fmt.Errorf("not a x509 cert")
}
dst = append(dst, cer.raw)
}
inst.rawChain = dst
return nil
}
func (inst *x509veri) verifyStandard() error {
chain := inst.rawChain
if chain == nil {
return fmt.Errorf("raw chain is nil")
}
size := len(chain)
if size < 1 {
return fmt.Errorf("empty cert chain")
}
targetCert := chain[0]
mid := make([]*x509.Certificate, 0)
for i, cer := range chain {
if 0 < i {
mid = append(mid, cer)
}
}
opts := x509.VerifyOptions{}
inst.prepareVerifiyOptionsWithIntermediates(&opts, mid)
inst.prepareVerifiyOptionsWithRoots(&opts)
opts.CurrentTime = time.Now()
chs, err := targetCert.Verify(opts)
if err != nil {
return err
}
if chs == nil {
return fmt.Errorf("chains is nil")
}
count := len(chs)
vlog.Debug("chains.count=", count)
return nil
}
func (inst *x509veri) prepareVerifiyOptionsWithRoots(opts *x509.VerifyOptions) {
pool := x509.NewCertPool()
src := inst.roots.ListAll()
for _, root := range src {
x509c, ok := root.GetEntity().(*x509cert)
if ok && x509c != nil {
raw := x509c.raw
if raw != nil {
pool.AddCert(raw)
}
}
}
opts.Roots = pool
}
func (inst *x509veri) prepareVerifiyOptionsWithIntermediates(opts *x509.VerifyOptions, src []*x509.Certificate) {
pool := x509.NewCertPool()
for _, cer := range src {
pool.AddCert(cer)
}
opts.Intermediates = pool
}