forked from hyperledger/fabric
-
Notifications
You must be signed in to change notification settings - Fork 0
/
key.go
120 lines (107 loc) · 3.01 KB
/
key.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
110
111
112
113
114
115
116
117
118
119
120
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package accesscontrol
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"math/big"
"net"
"time"
)
type KeyGenFunc func() (*certKeyPair, error)
type certKeyPair struct {
*CertKeyPair
crypto.Signer
cert *x509.Certificate
}
func (p *certKeyPair) privKeyString() string {
return base64.StdEncoding.EncodeToString(p.Key)
}
func (p *certKeyPair) pubKeyString() string {
return base64.StdEncoding.EncodeToString(p.Cert)
}
func newPrivKey() (*ecdsa.PrivateKey, []byte, error) {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, nil, err
}
privBytes, err := x509.MarshalECPrivateKey(privateKey)
if err != nil {
return nil, nil, err
}
return privateKey, privBytes, nil
}
func newCertTemplate() (x509.Certificate, error) {
sn, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
if err != nil {
return x509.Certificate{}, err
}
return x509.Certificate{
NotBefore: time.Now().Add(time.Hour * (-24)),
NotAfter: time.Now().Add(time.Hour * 24),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
SerialNumber: sn,
}, nil
}
func newCertKeyPair(isCA bool, isServer bool, host string, certSigner crypto.Signer, parent *x509.Certificate) (*certKeyPair, error) {
privateKey, privBytes, err := newPrivKey()
if err != nil {
return nil, err
}
template, err := newCertTemplate()
if err != nil {
return nil, err
}
tenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 10)
if isCA {
template.NotAfter = tenYearsFromNow
template.IsCA = true
template.KeyUsage |= x509.KeyUsageCertSign | x509.KeyUsageCRLSign
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny}
template.BasicConstraintsValid = true
} else {
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
}
if isServer {
template.NotAfter = tenYearsFromNow
template.ExtKeyUsage = append(template.ExtKeyUsage, x509.ExtKeyUsageServerAuth)
if ip := net.ParseIP(host); ip != nil {
logger.Debug("Classified", host, "as an IP address, adding it as an IP SAN")
template.IPAddresses = append(template.IPAddresses, ip)
} else {
logger.Debug("Classified", host, "as a hostname, adding it as a DNS SAN")
template.DNSNames = append(template.DNSNames, host)
}
}
// If no parent cert, it's a self signed cert
if parent == nil || certSigner == nil {
parent = &template
certSigner = privateKey
}
rawBytes, err := x509.CreateCertificate(rand.Reader, &template, parent, &privateKey.PublicKey, certSigner)
if err != nil {
return nil, err
}
pubKey := encodePEM("CERTIFICATE", rawBytes)
block, _ := pem.Decode(pubKey)
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, err
}
privKey := encodePEM("EC PRIVATE KEY", privBytes)
return &certKeyPair{
CertKeyPair: &CertKeyPair{
Key: privKey,
Cert: pubKey,
},
Signer: privateKey,
cert: cert,
}, nil
}