Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(60)

Side by Side Diff: cert/cert.go

Issue 70770043: all: use errgo instead of fmt.Errorf
Patch Set: all: use errgo instead of fmt.Errorf Created 11 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « bzr/bzr.go ('k') | cert/cert_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012, 2013 Canonical Ltd. 1 // Copyright 2012, 2013 Canonical Ltd.
2 // Licensed under the AGPLv3, see LICENCE file for details. 2 // Licensed under the AGPLv3, see LICENCE file for details.
3 3
4 package cert 4 package cert
5 5
6 import ( 6 import (
7 "crypto/rand" 7 "crypto/rand"
8 "crypto/rsa" 8 "crypto/rsa"
9 "crypto/sha1" 9 "crypto/sha1"
10 "crypto/tls" 10 "crypto/tls"
11 "crypto/x509" 11 "crypto/x509"
12 "crypto/x509/pkix" 12 "crypto/x509/pkix"
13 "encoding/pem" 13 "encoding/pem"
14 "errors"
15 "fmt" 14 "fmt"
16 "math/big" 15 "math/big"
17 "net" 16 "net"
18 "time" 17 "time"
19 18
20 » "github.com/errgo/errgo" 19 » "github.com/juju/errgo/errors"
21 ) 20 )
22 21
23 var KeyBits = 1024 22 var KeyBits = 1024
24 23
25 // ParseCert parses the given PEM-formatted X509 certificate. 24 // ParseCert parses the given PEM-formatted X509 certificate.
26 func ParseCert(certPEM []byte) (*x509.Certificate, error) { 25 func ParseCert(certPEM []byte) (*x509.Certificate, error) {
27 for len(certPEM) > 0 { 26 for len(certPEM) > 0 {
28 var certBlock *pem.Block 27 var certBlock *pem.Block
29 certBlock, certPEM = pem.Decode(certPEM) 28 certBlock, certPEM = pem.Decode(certPEM)
30 if certBlock == nil { 29 if certBlock == nil {
(...skipping 15 matching lines...) Expand all
46 return nil, nil, err 45 return nil, nil, err
47 } 46 }
48 47
49 cert, err := x509.ParseCertificate(tlsCert.Certificate[0]) 48 cert, err := x509.ParseCertificate(tlsCert.Certificate[0])
50 if err != nil { 49 if err != nil {
51 return nil, nil, err 50 return nil, nil, err
52 } 51 }
53 52
54 key, ok := tlsCert.PrivateKey.(*rsa.PrivateKey) 53 key, ok := tlsCert.PrivateKey.(*rsa.PrivateKey)
55 if !ok { 54 if !ok {
56 » » return nil, nil, fmt.Errorf("private key with unexpected type %T ", key) 55 » » return nil, nil, errors.Newf("private key with unexpected type % T", key)
57 } 56 }
58 return cert, key, nil 57 return cert, key, nil
59 } 58 }
60 59
61 // Verify verifies that the given server certificate is valid with 60 // Verify verifies that the given server certificate is valid with
62 // respect to the given CA certificate at the given time. 61 // respect to the given CA certificate at the given time.
63 func Verify(srvCertPEM, caCertPEM []byte, when time.Time) error { 62 func Verify(srvCertPEM, caCertPEM []byte, when time.Time) error {
64 caCert, err := ParseCert(caCertPEM) 63 caCert, err := ParseCert(caCertPEM)
65 if err != nil { 64 if err != nil {
66 » » return errgo.Annotate(err, "cannot parse CA certificate") 65 » » return errors.NoteMask(err, "cannot parse CA certificate")
67 } 66 }
68 srvCert, err := ParseCert(srvCertPEM) 67 srvCert, err := ParseCert(srvCertPEM)
69 if err != nil { 68 if err != nil {
70 » » return errgo.Annotate(err, "cannot parse server certificate") 69 » » return errors.NoteMask(err, "cannot parse server certificate")
71 } 70 }
72 pool := x509.NewCertPool() 71 pool := x509.NewCertPool()
73 pool.AddCert(caCert) 72 pool.AddCert(caCert)
74 opts := x509.VerifyOptions{ 73 opts := x509.VerifyOptions{
75 DNSName: "anyServer", 74 DNSName: "anyServer",
76 Roots: pool, 75 Roots: pool,
77 CurrentTime: when, 76 CurrentTime: when,
78 } 77 }
79 _, err = srvCert.Verify(opts) 78 _, err = srvCert.Verify(opts)
80 return err 79 return err
(...skipping 16 matching lines...) Expand all
97 NotBefore: now.UTC().Add(-5 * time.Minute), 96 NotBefore: now.UTC().Add(-5 * time.Minute),
98 NotAfter: expiry.UTC(), 97 NotAfter: expiry.UTC(),
99 SubjectKeyId: bigIntHash(key.N), 98 SubjectKeyId: bigIntHash(key.N),
100 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUs ageDigitalSignature | x509.KeyUsageCertSign, 99 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUs ageDigitalSignature | x509.KeyUsageCertSign,
101 IsCA: true, 100 IsCA: true,
102 MaxPathLen: 0, // Disallow delegation for now. 101 MaxPathLen: 0, // Disallow delegation for now.
103 BasicConstraintsValid: true, 102 BasicConstraintsValid: true,
104 } 103 }
105 certDER, err := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key) 104 certDER, err := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key)
106 if err != nil { 105 if err != nil {
107 » » return nil, nil, fmt.Errorf("canot create certificate: %v", err) 106 » » return nil, nil, errors.Notef(err, "canot create certificate")
108 } 107 }
109 certPEM = pem.EncodeToMemory(&pem.Block{ 108 certPEM = pem.EncodeToMemory(&pem.Block{
110 Type: "CERTIFICATE", 109 Type: "CERTIFICATE",
111 Bytes: certDER, 110 Bytes: certDER,
112 }) 111 })
113 keyPEM = pem.EncodeToMemory(&pem.Block{ 112 keyPEM = pem.EncodeToMemory(&pem.Block{
114 Type: "RSA PRIVATE KEY", 113 Type: "RSA PRIVATE KEY",
115 Bytes: x509.MarshalPKCS1PrivateKey(key), 114 Bytes: x509.MarshalPKCS1PrivateKey(key),
116 }) 115 })
117 return certPEM, keyPEM, nil 116 return certPEM, keyPEM, nil
118 } 117 }
119 118
120 // NewServer generates a certificate/key pair suitable for use by a server. 119 // NewServer generates a certificate/key pair suitable for use by a server.
121 func NewServer(caCertPEM, caKeyPEM []byte, expiry time.Time, hostnames []string) (certPEM, keyPEM []byte, err error) { 120 func NewServer(caCertPEM, caKeyPEM []byte, expiry time.Time, hostnames []string) (certPEM, keyPEM []byte, err error) {
122 return newLeaf(caCertPEM, caKeyPEM, expiry, hostnames, []x509.ExtKeyUsag e{x509.ExtKeyUsageServerAuth}) 121 return newLeaf(caCertPEM, caKeyPEM, expiry, hostnames, []x509.ExtKeyUsag e{x509.ExtKeyUsageServerAuth})
123 } 122 }
124 123
125 // NewClient generates a certificate/key pair suitable for client authentication . 124 // NewClient generates a certificate/key pair suitable for client authentication .
126 func NewClient(caCertPEM, caKeyPEM []byte, expiry time.Time) (certPEM, keyPEM [] byte, err error) { 125 func NewClient(caCertPEM, caKeyPEM []byte, expiry time.Time) (certPEM, keyPEM [] byte, err error) {
127 return newLeaf(caCertPEM, caKeyPEM, expiry, nil, []x509.ExtKeyUsage{x509 .ExtKeyUsageClientAuth}) 126 return newLeaf(caCertPEM, caKeyPEM, expiry, nil, []x509.ExtKeyUsage{x509 .ExtKeyUsageClientAuth})
128 } 127 }
129 128
130 // newLeaf generates a certificate/key pair suitable for use by a leaf node. 129 // newLeaf generates a certificate/key pair suitable for use by a leaf node.
131 func newLeaf(caCertPEM, caKeyPEM []byte, expiry time.Time, hostnames []string, e xtKeyUsage []x509.ExtKeyUsage) (certPEM, keyPEM []byte, err error) { 130 func newLeaf(caCertPEM, caKeyPEM []byte, expiry time.Time, hostnames []string, e xtKeyUsage []x509.ExtKeyUsage) (certPEM, keyPEM []byte, err error) {
132 tlsCert, err := tls.X509KeyPair(caCertPEM, caKeyPEM) 131 tlsCert, err := tls.X509KeyPair(caCertPEM, caKeyPEM)
133 if err != nil { 132 if err != nil {
134 return nil, nil, err 133 return nil, nil, err
135 } 134 }
136 if len(tlsCert.Certificate) != 1 { 135 if len(tlsCert.Certificate) != 1 {
137 » » return nil, nil, fmt.Errorf("more than one certificate for CA") 136 » » return nil, nil, errors.Newf("more than one certificate for CA")
138 } 137 }
139 caCert, err := x509.ParseCertificate(tlsCert.Certificate[0]) 138 caCert, err := x509.ParseCertificate(tlsCert.Certificate[0])
140 if err != nil { 139 if err != nil {
141 return nil, nil, err 140 return nil, nil, err
142 } 141 }
143 if !caCert.BasicConstraintsValid || !caCert.IsCA { 142 if !caCert.BasicConstraintsValid || !caCert.IsCA {
144 » » return nil, nil, fmt.Errorf("CA certificate is not a valid CA") 143 » » return nil, nil, errors.Newf("CA certificate is not a valid CA")
145 } 144 }
146 caKey, ok := tlsCert.PrivateKey.(*rsa.PrivateKey) 145 caKey, ok := tlsCert.PrivateKey.(*rsa.PrivateKey)
147 if !ok { 146 if !ok {
148 » » return nil, nil, fmt.Errorf("CA private key has unexpected type %T", tlsCert.PrivateKey) 147 » » return nil, nil, errors.Newf("CA private key has unexpected type %T", tlsCert.PrivateKey)
149 } 148 }
150 key, err := rsa.GenerateKey(rand.Reader, KeyBits) 149 key, err := rsa.GenerateKey(rand.Reader, KeyBits)
151 if err != nil { 150 if err != nil {
152 » » return nil, nil, fmt.Errorf("cannot generate key: %v", err) 151 » » return nil, nil, errors.Notef(err, "cannot generate key")
153 } 152 }
154 now := time.Now() 153 now := time.Now()
155 template := &x509.Certificate{ 154 template := &x509.Certificate{
156 SerialNumber: new(big.Int), 155 SerialNumber: new(big.Int),
157 Subject: pkix.Name{ 156 Subject: pkix.Name{
158 // This won't match host names with dots. The hostname 157 // This won't match host names with dots. The hostname
159 // is hardcoded when connecting to avoid the issue. 158 // is hardcoded when connecting to avoid the issue.
160 CommonName: "*", 159 CommonName: "*",
161 Organization: []string{"juju"}, 160 Organization: []string{"juju"},
162 }, 161 },
(...skipping 24 matching lines...) Expand all
187 Bytes: x509.MarshalPKCS1PrivateKey(key), 186 Bytes: x509.MarshalPKCS1PrivateKey(key),
188 }) 187 })
189 return certPEM, keyPEM, nil 188 return certPEM, keyPEM, nil
190 } 189 }
191 190
192 func bigIntHash(n *big.Int) []byte { 191 func bigIntHash(n *big.Int) []byte {
193 h := sha1.New() 192 h := sha1.New()
194 h.Write(n.Bytes()) 193 h.Write(n.Bytes())
195 return h.Sum(nil) 194 return h.Sum(nil)
196 } 195 }
OLDNEW
« no previous file with comments | « bzr/bzr.go ('k') | cert/cert_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b