diff options
Diffstat (limited to 'key_validator.go')
-rw-r--r-- | key_validator.go | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/key_validator.go b/key_validator.go index fe6eb7b..062d78c 100644 --- a/key_validator.go +++ b/key_validator.go | |||
@@ -4,11 +4,13 @@ import ( | |||
4 | "crypto/rsa" | 4 | "crypto/rsa" |
5 | "crypto/x509" | 5 | "crypto/x509" |
6 | "encoding/pem" | 6 | "encoding/pem" |
7 | "fmt" | 7 | "github.com/pkg/errors" |
8 | "gopkg.in/square/go-jose.v2" | 8 | "gopkg.in/square/go-jose.v2" |
9 | "io/ioutil" | 9 | "io/ioutil" |
10 | ) | 10 | ) |
11 | 11 | ||
12 | // TODO: CRL validation | ||
13 | |||
12 | type KeyValidator interface { | 14 | type KeyValidator interface { |
13 | Validate(jose.JSONWebKey) error | 15 | Validate(jose.JSONWebKey) error |
14 | LoadRootPEM(string) error | 16 | LoadRootPEM(string) error |
@@ -31,17 +33,17 @@ func NewKeyValidator(subject string) KeyValidator { | |||
31 | func (v *keyValidator) LoadRootPEM(filename string) error { | 33 | func (v *keyValidator) LoadRootPEM(filename string) error { |
32 | pem_data, err := ioutil.ReadFile(filename) | 34 | pem_data, err := ioutil.ReadFile(filename) |
33 | if err != nil { | 35 | if err != nil { |
34 | return err | 36 | return errors.WithStack(err) |
35 | } | 37 | } |
36 | 38 | ||
37 | pem_block, _ := pem.Decode(pem_data) | 39 | pem_block, _ := pem.Decode(pem_data) |
38 | if pem_block == nil { | 40 | if pem_block == nil { |
39 | return fmt.Errorf("PEM decode failed") | 41 | return errors.Errorf("PEM decode failed") |
40 | } | 42 | } |
41 | 43 | ||
42 | cert, err := x509.ParseCertificate(pem_block.Bytes) | 44 | cert, err := x509.ParseCertificate(pem_block.Bytes) |
43 | if err != nil { | 45 | if err != nil { |
44 | return err | 46 | return errors.WithStack(err) |
45 | } | 47 | } |
46 | 48 | ||
47 | v.roots.AddCert(cert) | 49 | v.roots.AddCert(cert) |
@@ -52,40 +54,40 @@ func (v *keyValidator) LoadRootPEM(filename string) error { | |||
52 | func (v *keyValidator) Validate(key jose.JSONWebKey) error { | 54 | func (v *keyValidator) Validate(key jose.JSONWebKey) error { |
53 | pk, ok := key.Key.(*rsa.PublicKey) | 55 | pk, ok := key.Key.(*rsa.PublicKey) |
54 | if !ok { | 56 | if !ok { |
55 | return fmt.Errorf("Key type is not RSA") | 57 | return errors.Errorf("Key type is not RSA") |
56 | } | 58 | } |
57 | 59 | ||
58 | if !v.algorithms.Contains(key.Algorithm) { | 60 | if !v.algorithms.Contains(key.Algorithm) { |
59 | return fmt.Errorf("Key algorithm is not supported") | 61 | return errors.Errorf("Key algorithm is not supported") |
60 | } | 62 | } |
61 | 63 | ||
62 | cert := key.Certificates[0] | 64 | cert := key.Certificates[0] |
63 | cpk, ok := cert.PublicKey.(*rsa.PublicKey) | 65 | cpk, ok := cert.PublicKey.(*rsa.PublicKey) |
64 | if !ok { | 66 | if !ok { |
65 | return fmt.Errorf("Public key is not RSA") | 67 | return errors.Errorf("Public key is not RSA") |
66 | } | 68 | } |
67 | 69 | ||
68 | if cpk.N.BitLen() < 2048 { | 70 | if cpk.N.BitLen() < 2048 { |
69 | return fmt.Errorf("Key length less than 2048 bits") | 71 | return errors.Errorf("Key length less than 2048 bits") |
70 | } | 72 | } |
71 | 73 | ||
72 | if cert.KeyUsage&x509.KeyUsageDigitalSignature != 1 { | 74 | if cert.KeyUsage&x509.KeyUsageDigitalSignature != 1 { |
73 | return fmt.Errorf("Certificate not valid for digital signatures") | 75 | return errors.Errorf("Certificate not valid for digital signatures") |
74 | } | 76 | } |
75 | 77 | ||
76 | err := v.validateCertificateChain(key.Certificates) | 78 | err := v.validateCertificateChain(key.Certificates) |
77 | if err != nil { | 79 | if err != nil { |
78 | return err | 80 | return errors.WithStack(err) |
79 | } | 81 | } |
80 | 82 | ||
81 | err = v.validateCertificateCRL(cert) | 83 | err = v.validateCertificateCRL(cert) |
82 | if err != nil { | 84 | if err != nil { |
83 | return err | 85 | return errors.WithStack(err) |
84 | } | 86 | } |
85 | 87 | ||
86 | err = v.validatePublicKeyInCertificate(pk, cpk) | 88 | err = v.validatePublicKeyInCertificate(pk, cpk) |
87 | if err != nil { | 89 | if err != nil { |
88 | return err | 90 | return errors.WithStack(err) |
89 | } | 91 | } |
90 | 92 | ||
91 | return nil | 93 | return nil |
@@ -116,15 +118,15 @@ func (v *keyValidator) validateCertificateChain(chain []*x509.Certificate) error | |||
116 | 118 | ||
117 | chains, err := chain[0].Verify(vo) | 119 | chains, err := chain[0].Verify(vo) |
118 | if err != nil { | 120 | if err != nil { |
119 | return err | 121 | return errors.WithStack(err) |
120 | } | 122 | } |
121 | 123 | ||
122 | if len(chains) <= 0 { | 124 | if len(chains) <= 0 { |
123 | return fmt.Errorf("No valid certificate chains found") | 125 | return errors.Errorf("No valid certificate chains found") |
124 | } | 126 | } |
125 | 127 | ||
126 | if chain[0].Subject.CommonName != v.pkiSubject { | 128 | if chain[0].Subject.CommonName != v.pkiSubject { |
127 | return fmt.Errorf("Invalid certificate subject name") | 129 | return errors.Errorf("Invalid certificate subject name") |
128 | } | 130 | } |
129 | 131 | ||
130 | return nil | 132 | return nil |
@@ -133,11 +135,11 @@ func (v *keyValidator) validateCertificateChain(chain []*x509.Certificate) error | |||
133 | // validate first item of x5c matches n and e | 135 | // validate first item of x5c matches n and e |
134 | func (v *keyValidator) validatePublicKeyInCertificate(pk *rsa.PublicKey, cpk *rsa.PublicKey) error { | 136 | func (v *keyValidator) validatePublicKeyInCertificate(pk *rsa.PublicKey, cpk *rsa.PublicKey) error { |
135 | if cpk.E != pk.E { | 137 | if cpk.E != pk.E { |
136 | return fmt.Errorf("E in key and E in cert do not match") | 138 | return errors.Errorf("E in key and E in cert do not match") |
137 | } | 139 | } |
138 | 140 | ||
139 | if pk.N.Cmp(cpk.N) != 0 { | 141 | if pk.N.Cmp(cpk.N) != 0 { |
140 | return fmt.Errorf("N in key and N in cert do not match") | 142 | return errors.Errorf("N in key and N in cert do not match") |
141 | } | 143 | } |
142 | 144 | ||
143 | return nil | 145 | return nil |