Skip to content

Commit 80e7ab8

Browse files
committed
Consolidate PKI choices in a single file
It is easier to evaluate curves, curve parameters, signature algorithms, key lengths, certificate constraints, and validity periods when they are all in one place.
1 parent d3721cd commit 80e7ab8

File tree

4 files changed

+92
-106
lines changed

4 files changed

+92
-106
lines changed

internal/pki/common.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"crypto/elliptic"
2121
"crypto/rand"
2222
"crypto/x509"
23+
"crypto/x509/pkix"
2324
"math/big"
2425
"time"
2526
)
@@ -44,3 +45,62 @@ func generateKey() (*ecdsa.PrivateKey, error) {
4445
func generateSerialNumber() (*big.Int, error) {
4546
return rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
4647
}
48+
49+
func generateLeafCertificate(
50+
signer *x509.Certificate, signerPrivate *ecdsa.PrivateKey,
51+
signeePublic *ecdsa.PublicKey, serialNumber *big.Int,
52+
commonName string, dnsNames []string,
53+
) (*x509.Certificate, error) {
54+
const leafExpiration = time.Hour * 24 * 365
55+
const leafStartValid = time.Hour * -1
56+
57+
now := currentTime()
58+
template := &x509.Certificate{
59+
BasicConstraintsValid: true,
60+
DNSNames: dnsNames,
61+
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
62+
NotBefore: now.Add(leafStartValid),
63+
NotAfter: now.Add(leafExpiration),
64+
SerialNumber: serialNumber,
65+
SignatureAlgorithm: certificateSignatureAlgorithm,
66+
Subject: pkix.Name{
67+
CommonName: commonName,
68+
},
69+
}
70+
71+
bytes, err := x509.CreateCertificate(rand.Reader, template, signer,
72+
signeePublic, signerPrivate)
73+
74+
parsed, _ := x509.ParseCertificate(bytes)
75+
return parsed, err
76+
}
77+
78+
func generateRootCertificate(
79+
privateKey *ecdsa.PrivateKey, serialNumber *big.Int,
80+
) (*x509.Certificate, error) {
81+
const rootCommonName = "postgres-operator-ca"
82+
const rootExpiration = time.Hour * 24 * 365 * 10
83+
const rootStartValid = time.Hour * -1
84+
85+
now := currentTime()
86+
template := &x509.Certificate{
87+
BasicConstraintsValid: true,
88+
IsCA: true,
89+
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
90+
MaxPathLenZero: true, // there are no intermediate certificates
91+
NotBefore: now.Add(rootStartValid),
92+
NotAfter: now.Add(rootExpiration),
93+
SerialNumber: serialNumber,
94+
SignatureAlgorithm: certificateSignatureAlgorithm,
95+
Subject: pkix.Name{
96+
CommonName: rootCommonName,
97+
},
98+
}
99+
100+
// A root certificate is self-signed, so pass in the template twice.
101+
bytes, err := x509.CreateCertificate(rand.Reader, template, template,
102+
privateKey.Public(), privateKey)
103+
104+
parsed, _ := x509.ParseCertificate(bytes)
105+
return parsed, err
106+
}

internal/pki/leaf.go

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,8 @@ package pki
1717

1818
import (
1919
"context"
20-
"crypto/ecdsa"
21-
"crypto/rand"
22-
"crypto/x509"
23-
"crypto/x509/pkix"
24-
"math/big"
25-
"time"
2620
)
2721

28-
// LeafCertificate is a certificate and private key pair that can be validated
29-
// by RootCertificateAuthority.
30-
type LeafCertificate struct {
31-
Certificate Certificate
32-
PrivateKey PrivateKey
33-
}
34-
3522
// LeafCertIsBad checks at least one leaf cert has been generated, the basic constraints
3623
// are valid and it has been verified with the root certpool
3724
//
@@ -45,32 +32,3 @@ func LeafCertIsBad(
4532
) bool {
4633
return !rootCertCA.leafIsValid(leaf)
4734
}
48-
49-
func generateLeafCertificate(
50-
signer *x509.Certificate, signerPrivate *ecdsa.PrivateKey,
51-
signeePublic *ecdsa.PublicKey, serialNumber *big.Int,
52-
commonName string, dnsNames []string,
53-
) (*x509.Certificate, error) {
54-
const leafExpiration = time.Hour * 24 * 365
55-
const leafStartValid = time.Hour * -1
56-
57-
now := currentTime()
58-
template := &x509.Certificate{
59-
BasicConstraintsValid: true,
60-
DNSNames: dnsNames,
61-
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
62-
NotBefore: now.Add(leafStartValid),
63-
NotAfter: now.Add(leafExpiration),
64-
SerialNumber: serialNumber,
65-
SignatureAlgorithm: certificateSignatureAlgorithm,
66-
Subject: pkix.Name{
67-
CommonName: commonName,
68-
},
69-
}
70-
71-
bytes, err := x509.CreateCertificate(rand.Reader, template, signer,
72-
signeePublic, signerPrivate)
73-
74-
parsed, _ := x509.ParseCertificate(bytes)
75-
return parsed, err
76-
}

internal/pki/pki.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,38 @@ func (k PrivateKey) Equal(other PrivateKey) bool {
5858
return k.ecdsa.Equal(other.ecdsa)
5959
}
6060

61+
// LeafCertificate is a certificate and private key pair that can be validated
62+
// by RootCertificateAuthority.
63+
type LeafCertificate struct {
64+
Certificate Certificate
65+
PrivateKey PrivateKey
66+
}
67+
68+
// RootCertificateAuthority is a certificate and private key pair that can
69+
// generate other certificates.
70+
type RootCertificateAuthority struct {
71+
Certificate Certificate
72+
PrivateKey PrivateKey
73+
}
74+
75+
// NewRootCertificateAuthority generates a new key and self-signed certificate
76+
// for issuing other certificates.
77+
func NewRootCertificateAuthority() (*RootCertificateAuthority, error) {
78+
var root RootCertificateAuthority
79+
var serial *big.Int
80+
81+
key, err := generateKey()
82+
if err == nil {
83+
serial, err = generateSerialNumber()
84+
}
85+
if err == nil {
86+
root.PrivateKey.ecdsa = key
87+
root.Certificate.x509, err = generateRootCertificate(key, serial)
88+
}
89+
90+
return &root, err
91+
}
92+
6193
// RootIsValid checks if root is valid according to this package's policies.
6294
func RootIsValid(root *RootCertificateAuthority) bool {
6395
if root == nil || root.Certificate.x509 == nil {

internal/pki/root.go

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -15,40 +15,6 @@
1515

1616
package pki
1717

18-
import (
19-
"crypto/ecdsa"
20-
"crypto/rand"
21-
"crypto/x509"
22-
"crypto/x509/pkix"
23-
"math/big"
24-
"time"
25-
)
26-
27-
// RootCertificateAuthority is a certificate and private key pair that can
28-
// generate other certificates.
29-
type RootCertificateAuthority struct {
30-
Certificate Certificate
31-
PrivateKey PrivateKey
32-
}
33-
34-
// NewRootCertificateAuthority generates a new key and self-signed certificate
35-
// for issuing other certificates.
36-
func NewRootCertificateAuthority() (*RootCertificateAuthority, error) {
37-
var root RootCertificateAuthority
38-
var serial *big.Int
39-
40-
key, err := generateKey()
41-
if err == nil {
42-
serial, err = generateSerialNumber()
43-
}
44-
if err == nil {
45-
root.PrivateKey.ecdsa = key
46-
root.Certificate.x509, err = generateRootCertificate(key, serial)
47-
}
48-
49-
return &root, err
50-
}
51-
5218
// RootCAIsBad checks that at least one root CA has been generated and that
5319
// all returned certs are CAs and not expired
5420
//
@@ -59,33 +25,3 @@ func NewRootCertificateAuthority() (*RootCertificateAuthority, error) {
5925
func RootCAIsBad(root *RootCertificateAuthority) bool {
6026
return !RootIsValid(root)
6127
}
62-
63-
func generateRootCertificate(
64-
privateKey *ecdsa.PrivateKey, serialNumber *big.Int,
65-
) (*x509.Certificate, error) {
66-
const rootCommonName = "postgres-operator-ca"
67-
const rootExpiration = time.Hour * 24 * 365 * 10
68-
const rootStartValid = time.Hour * -1
69-
70-
now := currentTime()
71-
template := &x509.Certificate{
72-
BasicConstraintsValid: true,
73-
IsCA: true,
74-
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
75-
MaxPathLenZero: true, // there are no intermediate certificates
76-
NotBefore: now.Add(rootStartValid),
77-
NotAfter: now.Add(rootExpiration),
78-
SerialNumber: serialNumber,
79-
SignatureAlgorithm: certificateSignatureAlgorithm,
80-
Subject: pkix.Name{
81-
CommonName: rootCommonName,
82-
},
83-
}
84-
85-
// A root certificate is self-signed, so pass in the template twice.
86-
bytes, err := x509.CreateCertificate(rand.Reader, template, template,
87-
privateKey.Public(), privateKey)
88-
89-
parsed, _ := x509.ParseCertificate(bytes)
90-
return parsed, err
91-
}

0 commit comments

Comments
 (0)