@@ -8,7 +8,9 @@ package ca
8
8
import (
9
9
"crypto"
10
10
"crypto/ecdsa"
11
+ "crypto/elliptic"
11
12
"crypto/rand"
13
+ "crypto/sha256"
12
14
"crypto/x509"
13
15
"crypto/x509/pkix"
14
16
"encoding/pem"
@@ -20,7 +22,6 @@ import (
20
22
"strings"
21
23
"time"
22
24
23
- "github.com/hyperledger/fabric/bccsp/utils"
24
25
"github.com/hyperledger/fabric/internal/cryptogen/csp"
25
26
"github.com/pkg/errors"
26
27
)
@@ -33,96 +34,131 @@ type CA struct {
33
34
OrganizationalUnit string
34
35
StreetAddress string
35
36
PostalCode string
36
- //SignKey *ecdsa.PrivateKey
37
- Signer crypto.Signer
38
- SignCert * x509.Certificate
37
+ Signer crypto.Signer
38
+ SignCert * x509.Certificate
39
39
}
40
40
41
41
// NewCA creates an instance of CA and saves the signing key pair in
42
42
// baseDir/name
43
- func NewCA (baseDir , org , name , country , province , locality , orgUnit , streetAddress , postalCode string ) (* CA , error ) {
43
+ func NewCA (
44
+ baseDir ,
45
+ org ,
46
+ name ,
47
+ country ,
48
+ province ,
49
+ locality ,
50
+ orgUnit ,
51
+ streetAddress ,
52
+ postalCode string ,
53
+ ) (* CA , error ) {
44
54
45
- var response error
46
55
var ca * CA
47
56
48
57
err := os .MkdirAll (baseDir , 0755 )
49
- if err == nil {
50
- priv , signer , err := csp .GeneratePrivateKey (baseDir )
51
- response = err
52
- if err == nil {
53
- // get public signing certificate
54
- ecPubKey , err := csp .GetECPublicKey (priv )
55
- response = err
56
- if err == nil {
57
- template := x509Template ()
58
- //this is a CA
59
- template .IsCA = true
60
- template .KeyUsage |= x509 .KeyUsageDigitalSignature |
61
- x509 .KeyUsageKeyEncipherment | x509 .KeyUsageCertSign |
62
- x509 .KeyUsageCRLSign
63
- template .ExtKeyUsage = []x509.ExtKeyUsage {
64
- x509 .ExtKeyUsageClientAuth ,
65
- x509 .ExtKeyUsageServerAuth ,
66
- }
67
-
68
- //set the organization for the subject
69
- subject := subjectTemplateAdditional (country , province , locality , orgUnit , streetAddress , postalCode )
70
- subject .Organization = []string {org }
71
- subject .CommonName = name
72
-
73
- template .Subject = subject
74
- template .SubjectKeyId = priv .SKI ()
75
-
76
- x509Cert , err := genCertificateECDSA (baseDir , name , & template , & template ,
77
- ecPubKey , signer )
78
- response = err
79
- if err == nil {
80
- ca = & CA {
81
- Name : name ,
82
- Signer : signer ,
83
- SignCert : x509Cert ,
84
- Country : country ,
85
- Province : province ,
86
- Locality : locality ,
87
- OrganizationalUnit : orgUnit ,
88
- StreetAddress : streetAddress ,
89
- PostalCode : postalCode ,
90
- }
91
- }
92
- }
93
- }
58
+ if err != nil {
59
+ return nil , err
60
+ }
61
+
62
+ priv , err := csp .GeneratePrivateKey (baseDir )
63
+ if err != nil {
64
+ return nil , err
65
+ }
66
+
67
+ template := x509Template ()
68
+ //this is a CA
69
+ template .IsCA = true
70
+ template .KeyUsage |= x509 .KeyUsageDigitalSignature |
71
+ x509 .KeyUsageKeyEncipherment | x509 .KeyUsageCertSign |
72
+ x509 .KeyUsageCRLSign
73
+ template .ExtKeyUsage = []x509.ExtKeyUsage {
74
+ x509 .ExtKeyUsageClientAuth ,
75
+ x509 .ExtKeyUsageServerAuth ,
76
+ }
77
+
78
+ //set the organization for the subject
79
+ subject := subjectTemplateAdditional (country , province , locality , orgUnit , streetAddress , postalCode )
80
+ subject .Organization = []string {org }
81
+ subject .CommonName = name
82
+
83
+ template .Subject = subject
84
+ template .SubjectKeyId = computeSKI (priv )
85
+
86
+ x509Cert , err := genCertificateECDSA (
87
+ baseDir ,
88
+ name ,
89
+ & template ,
90
+ & template ,
91
+ & priv .PublicKey ,
92
+ priv ,
93
+ )
94
+ if err != nil {
95
+ return nil , err
96
+ }
97
+ ca = & CA {
98
+ Name : name ,
99
+ Signer : & csp.ECDSASigner {
100
+ PrivateKey : priv ,
101
+ },
102
+ SignCert : x509Cert ,
103
+ Country : country ,
104
+ Province : province ,
105
+ Locality : locality ,
106
+ OrganizationalUnit : orgUnit ,
107
+ StreetAddress : streetAddress ,
108
+ PostalCode : postalCode ,
94
109
}
95
- return ca , response
110
+
111
+ return ca , err
96
112
}
97
113
98
114
// SignCertificate creates a signed certificate based on a built-in template
99
115
// and saves it in baseDir/name
100
- func (ca * CA ) SignCertificate (baseDir , name string , ous , sans []string , pub * ecdsa.PublicKey ,
101
- ku x509.KeyUsage , eku []x509.ExtKeyUsage ) (* x509.Certificate , error ) {
116
+ func (ca * CA ) SignCertificate (
117
+ baseDir ,
118
+ name string ,
119
+ orgUnits ,
120
+ alternateNames []string ,
121
+ pub * ecdsa.PublicKey ,
122
+ ku x509.KeyUsage ,
123
+ eku []x509.ExtKeyUsage ,
124
+ ) (* x509.Certificate , error ) {
102
125
103
126
template := x509Template ()
104
127
template .KeyUsage = ku
105
128
template .ExtKeyUsage = eku
106
129
107
130
//set the organization for the subject
108
- subject := subjectTemplateAdditional (ca .Country , ca .Province , ca .Locality , ca .OrganizationalUnit , ca .StreetAddress , ca .PostalCode )
131
+ subject := subjectTemplateAdditional (
132
+ ca .Country ,
133
+ ca .Province ,
134
+ ca .Locality ,
135
+ ca .OrganizationalUnit ,
136
+ ca .StreetAddress ,
137
+ ca .PostalCode ,
138
+ )
109
139
subject .CommonName = name
110
140
111
- subject .OrganizationalUnit = append (subject .OrganizationalUnit , ous ... )
141
+ subject .OrganizationalUnit = append (subject .OrganizationalUnit , orgUnits ... )
112
142
113
143
template .Subject = subject
114
- for _ , san := range sans {
144
+ for _ , san := range alternateNames {
115
145
// try to parse as an IP address first
116
146
ip := net .ParseIP (san )
117
147
if ip != nil {
118
148
template .IPAddresses = append (template .IPAddresses , ip )
119
149
} else {
120
- template .DNSNames = append (template .DNSNames , san )
150
+ template .DNSNames = append (template .DNSNames , alternateNames ... )
121
151
}
122
152
}
123
153
124
- cert , err := genCertificateECDSA (baseDir , name , & template , ca .SignCert ,
125
- pub , ca .Signer )
154
+ cert , err := genCertificateECDSA (
155
+ baseDir ,
156
+ name ,
157
+ & template ,
158
+ ca .SignCert ,
159
+ pub ,
160
+ ca .Signer ,
161
+ )
126
162
127
163
if err != nil {
128
164
return nil , err
@@ -131,6 +167,16 @@ func (ca *CA) SignCertificate(baseDir, name string, ous, sans []string, pub *ecd
131
167
return cert , nil
132
168
}
133
169
170
+ // compute Subject Key Identifier
171
+ func computeSKI (privKey * ecdsa.PrivateKey ) []byte {
172
+ // Marshall the public key
173
+ raw := elliptic .Marshal (privKey .Curve , privKey .PublicKey .X , privKey .PublicKey .Y )
174
+
175
+ // Hash it
176
+ hash := sha256 .Sum256 (raw )
177
+ return hash [:]
178
+ }
179
+
134
180
// default template for X509 subject
135
181
func subjectTemplate () pkix.Name {
136
182
return pkix.Name {
@@ -141,7 +187,14 @@ func subjectTemplate() pkix.Name {
141
187
}
142
188
143
189
// Additional for X509 subject
144
- func subjectTemplateAdditional (country , province , locality , orgUnit , streetAddress , postalCode string ) pkix.Name {
190
+ func subjectTemplateAdditional (
191
+ country ,
192
+ province ,
193
+ locality ,
194
+ orgUnit ,
195
+ streetAddress ,
196
+ postalCode string ,
197
+ ) pkix.Name {
145
198
name := subjectTemplate ()
146
199
if len (country ) >= 1 {
147
200
name .Country = []string {country }
@@ -189,8 +242,14 @@ func x509Template() x509.Certificate {
189
242
}
190
243
191
244
// generate a signed X509 certificate using ECDSA
192
- func genCertificateECDSA (baseDir , name string , template , parent * x509.Certificate , pub * ecdsa.PublicKey ,
193
- priv interface {}) (* x509.Certificate , error ) {
245
+ func genCertificateECDSA (
246
+ baseDir ,
247
+ name string ,
248
+ template ,
249
+ parent * x509.Certificate ,
250
+ pub * ecdsa.PublicKey ,
251
+ priv interface {},
252
+ ) (* x509.Certificate , error ) {
194
253
195
254
//create the x509 public cert
196
255
certBytes , err := x509 .CreateCertificate (rand .Reader , template , parent , pub , priv )
@@ -233,7 +292,7 @@ func LoadCertificateECDSA(certPath string) (*x509.Certificate, error) {
233
292
if block == nil || block .Type != "CERTIFICATE" {
234
293
return errors .Errorf ("%s: wrong PEM encoding" , path )
235
294
}
236
- cert , err = utils . DERToX509Certificate (block .Bytes )
295
+ cert , err = x509 . ParseCertificate (block .Bytes )
237
296
if err != nil {
238
297
return errors .Errorf ("%s: wrong DER encoding" , path )
239
298
}
0 commit comments