Skip to content
File

Blob: spec/pki/pki_test.go

go156 lines
1package pki
2 
3import (
4 "crypto/ed25519"
5 "crypto/rand"
6 "crypto/tls"
7 "crypto/x509"
8 "crypto/x509/pkix"
9 "math/big"
10 "testing"
11 "time"
12 
13 "github.com/stretchr/testify/require"
14 "go.uber.org/zap/zaptest"
15)
16 
17const (
18 testCommonName = "test cn"
19)
20 
21func generateCA(as *require.Assertions) tls.Certificate {
22 ca := &x509.Certificate{
23 SerialNumber: big.NewInt(1234),
24 Subject: pkix.Name{
25 CommonName: "test ca",
26 },
27 NotBefore: time.Now(),
28 NotAfter: time.Now().AddDate(10, 0, 0),
29 IsCA: true,
30 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
31 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
32 BasicConstraintsValid: true,
33 }
34 
35 caPubKey, caPrivKey, err := ed25519.GenerateKey(rand.Reader)
36 as.NoError(err)
37 
38 caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, caPubKey, caPrivKey)
39 as.NoError(err)
40 
41 return tls.Certificate{
42 Certificate: [][]byte{caBytes},
43 PrivateKey: caPrivKey,
44 }
45}
46 
47func TestGenerateCertificate(t *testing.T) {
48 logger := zaptest.NewLogger(t)
49 as := require.New(t)
50 pubKey, _ := GeneratePrivKey()
51 
52 ca := generateCA(as)
53 caCert, err := x509.ParseCertificate(ca.Certificate[0])
54 as.NoError(err)
55 
56 der, err := GenerateCertificate(logger, ca, IdentityRequest{
57 PublicKey: pubKey,
58 Subject: pkix.Name{
59 CommonName: testCommonName,
60 },
61 })
62 as.NoError(err)
63 
64 cert, err := x509.ParseCertificate(der)
65 as.NoError(err)
66 as.Equal(testCommonName, cert.Subject.CommonName)
67 
68 correctCa := x509.NewCertPool()
69 correctCa.AddCert(caCert)
70 
71 _, err = cert.Verify(x509.VerifyOptions{
72 Roots: correctCa,
73 KeyUsages: []x509.ExtKeyUsage{
74 x509.ExtKeyUsageClientAuth,
75 },
76 })
77 as.NoError(err)
78 
79 ca2 := generateCA(as)
80 caCert2, err := x509.ParseCertificate(ca2.Certificate[0])
81 as.NoError(err)
82 
83 wrongCa := x509.NewCertPool()
84 wrongCa.AddCert(caCert2)
85 
86 _, err = cert.Verify(x509.VerifyOptions{
87 Roots: wrongCa,
88 KeyUsages: []x509.ExtKeyUsage{
89 x509.ExtKeyUsageClientAuth,
90 },
91 })
92 as.Error(err)
93}
94 
95func TestGenerateCertificate_CustomValidity(t *testing.T) {
96 logger := zaptest.NewLogger(t)
97 as := require.New(t)
98 pubKey, _ := GeneratePrivKey()
99 
100 ca := generateCA(as)
101 
102 customValidity := time.Hour * 2
103 
104 der, err := GenerateCertificate(logger, ca, IdentityRequest{
105 PublicKey: pubKey,
106 Subject: pkix.Name{
107 CommonName: "custom-validity-test",
108 },
109 ValidFor: customValidity,
110 })
111 as.NoError(err)
112 
113 cert, err := x509.ParseCertificate(der)
114 as.NoError(err)
115 
116 // Verify the certificate validity is approximately the custom duration
117 // Allow 1 minute tolerance for test execution time
118 actualValidity := cert.NotAfter.Sub(cert.NotBefore)
119 as.InDelta(customValidity.Seconds(), actualValidity.Seconds(), 60)
120}
121 
122func TestGenerateCertificate_DefaultValidity(t *testing.T) {
123 logger := zaptest.NewLogger(t)
124 as := require.New(t)
125 pubKey, _ := GeneratePrivKey()
126 
127 ca := generateCA(as)
128 
129 der, err := GenerateCertificate(logger, ca, IdentityRequest{
130 PublicKey: pubKey,
131 Subject: pkix.Name{
132 CommonName: "default-validity-test",
133 },
134 // ValidFor not set, should default to DefaultCertValidity
135 })
136 as.NoError(err)
137 
138 cert, err := x509.ParseCertificate(der)
139 as.NoError(err)
140 
141 // Verify the certificate validity matches the default constant
142 actualValidity := cert.NotAfter.Sub(cert.NotBefore)
143 // Allow 1 minute tolerance for test execution time
144 as.InDelta(DefaultCertValidity.Seconds(), actualValidity.Seconds(), 60)
145}
146 
147func TestPrivateKey(t *testing.T) {
148 as := require.New(t)
149 pubKey, keyPem := GeneratePrivKey()
150 un, err := UnmarshalPrivateKey([]byte(keyPem))
151 as.NoError(err)
152 
153 privKey := ed25519.PrivateKey(un)
154 as.EqualValues(pubKey, privKey.Public().(ed25519.PublicKey))
155}