kuma

Форк
0
/
cert.go 
180 строк · 4.6 Кб
1
package tls
2

3
import (
4
	"crypto"
5
	"crypto/ecdsa"
6
	"crypto/elliptic"
7
	"crypto/rand"
8
	"crypto/x509"
9
	"crypto/x509/pkix"
10
	"math/big"
11
	"net"
12
	"time"
13

14
	"github.com/pkg/errors"
15

16
	"github.com/kumahq/kuma/pkg/core"
17
	util_rsa "github.com/kumahq/kuma/pkg/util/rsa"
18
)
19

20
var DefaultValidityPeriod = 10 * 365 * 24 * time.Hour
21

22
type CertType string
23

24
const (
25
	ServerCertType              CertType = "server"
26
	ClientCertType              CertType = "client"
27
	DefaultAllowedClockSkew              = 5 * time.Minute
28
	DefaultCACertValidityPeriod          = 10 * 365 * 24 * time.Hour
29
)
30

31
type KeyType func() (crypto.Signer, error)
32

33
var ECDSAKeyType KeyType = func() (crypto.Signer, error) {
34
	return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
35
}
36

37
var RSAKeyType KeyType = func() (crypto.Signer, error) {
38
	return util_rsa.GenerateKey(util_rsa.DefaultKeySize)
39
}
40

41
var DefaultKeyType = RSAKeyType
42

43
func NewSelfSignedCert(certType CertType, keyType KeyType, hosts ...string) (KeyPair, error) {
44
	key, err := keyType()
45
	if err != nil {
46
		return KeyPair{}, errors.Wrap(err, "failed to generate TLS key")
47
	}
48

49
	csr, err := newCert(nil, certType, hosts...)
50
	if err != nil {
51
		return KeyPair{}, err
52
	}
53
	certDerBytes, err := x509.CreateCertificate(rand.Reader, &csr, &csr, key.Public(), key)
54
	if err != nil {
55
		return KeyPair{}, errors.Wrap(err, "failed to generate TLS certificate")
56
	}
57

58
	certBytes, err := pemEncodeCert(certDerBytes)
59
	if err != nil {
60
		return KeyPair{}, err
61
	}
62

63
	keyBytes, err := pemEncodeKey(key)
64
	if err != nil {
65
		return KeyPair{}, err
66
	}
67

68
	return KeyPair{
69
		CertPEM: certBytes,
70
		KeyPEM:  keyBytes,
71
	}, nil
72
}
73

74
// NewCert generates certificate that is signed by the CA (parent)
75
func NewCert(
76
	parent x509.Certificate,
77
	parentKey crypto.Signer,
78
	certType CertType,
79
	keyType KeyType,
80
	hosts ...string,
81
) (KeyPair, error) {
82
	key, err := keyType()
83
	if err != nil {
84
		return KeyPair{}, errors.Wrap(err, "failed to generate TLS key")
85
	}
86

87
	csr, err := newCert(&parent.Subject, certType, hosts...)
88
	if err != nil {
89
		return KeyPair{}, err
90
	}
91

92
	certDerBytes, err := x509.CreateCertificate(rand.Reader, &csr, &parent, key.Public(), parentKey)
93
	if err != nil {
94
		return KeyPair{}, errors.Wrap(err, "failed to generate TLS certificate")
95
	}
96

97
	certBytes, err := pemEncodeCert(certDerBytes)
98
	if err != nil {
99
		return KeyPair{}, err
100
	}
101

102
	keyBytes, err := pemEncodeKey(key)
103
	if err != nil {
104
		return KeyPair{}, err
105
	}
106

107
	return KeyPair{
108
		CertPEM: certBytes,
109
		KeyPEM:  keyBytes,
110
	}, nil
111
}
112

113
func newCert(issuer *pkix.Name, certType CertType, hosts ...string) (x509.Certificate, error) {
114
	notBefore := time.Now()
115
	notAfter := notBefore.Add(DefaultValidityPeriod)
116
	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
117
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
118
	if err != nil {
119
		return x509.Certificate{}, errors.Wrap(err, "failed to generate serial number")
120
	}
121
	csr := x509.Certificate{
122
		SerialNumber:          serialNumber,
123
		Subject:               pkix.Name{},
124
		NotBefore:             notBefore,
125
		NotAfter:              notAfter,
126
		IsCA:                  issuer == nil,
127
		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
128
		ExtKeyUsage:           []x509.ExtKeyUsage{},
129
		BasicConstraintsValid: true,
130
	}
131
	if issuer != nil {
132
		csr.Issuer = *issuer
133
	} else {
134
		csr.KeyUsage |= x509.KeyUsageCertSign
135
	}
136
	switch certType {
137
	case ServerCertType:
138
		csr.ExtKeyUsage = append(csr.ExtKeyUsage, x509.ExtKeyUsageServerAuth)
139
	case ClientCertType:
140
		csr.ExtKeyUsage = append(csr.ExtKeyUsage, x509.ExtKeyUsageClientAuth)
141
	default:
142
		return x509.Certificate{}, errors.Errorf("invalid certificate type %q, expected either %q or %q",
143
			certType, ServerCertType, ClientCertType)
144
	}
145
	for _, host := range hosts {
146
		if ip := net.ParseIP(host); ip != nil {
147
			csr.IPAddresses = append(csr.IPAddresses, ip)
148
		} else {
149
			csr.DNSNames = append(csr.DNSNames, host)
150
		}
151
	}
152
	return csr, nil
153
}
154

155
func GenerateCA(keyType KeyType, subject pkix.Name) (*KeyPair, error) {
156
	key, err := keyType()
157
	if err != nil {
158
		return nil, errors.Wrap(err, "failed to generate a private key")
159
	}
160

161
	now := core.Now()
162
	notBefore := now.Add(-DefaultAllowedClockSkew)
163
	notAfter := now.Add(DefaultCACertValidityPeriod)
164
	caTemplate := &x509.Certificate{
165
		SerialNumber:          big.NewInt(0),
166
		Subject:               subject,
167
		NotBefore:             notBefore,
168
		NotAfter:              notAfter,
169
		KeyUsage:              x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
170
		BasicConstraintsValid: true,
171
		IsCA:                  true,
172
		PublicKey:             key.Public(),
173
	}
174

175
	ca, err := x509.CreateCertificate(rand.Reader, caTemplate, caTemplate, key.Public(), key)
176
	if err != nil {
177
		return nil, err
178
	}
179
	return ToKeyPair(key, ca)
180
}
181

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.