Skip to content
File

Blob: pki/client_rpc_test.go

go258 lines
1package pki
2 
3import (
4 "context"
5 "crypto/ed25519"
6 "crypto/rand"
7 "crypto/tls"
8 "crypto/x509"
9 "crypto/x509/pkix"
10 "math/big"
11 "testing"
12 "time"
13 
14 "go.miragespace.co/specter/spec/pki"
15 
16 "github.com/stretchr/testify/require"
17 "go.uber.org/zap/zaptest"
18)
19 
20func generateCA(as *require.Assertions) tls.Certificate {
21 ca := &x509.Certificate{
22 SerialNumber: big.NewInt(1234),
23 Subject: pkix.Name{
24 CommonName: "test ca",
25 },
26 NotBefore: time.Now(),
27 NotAfter: time.Now().AddDate(10, 0, 0),
28 IsCA: true,
29 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
30 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
31 BasicConstraintsValid: true,
32 }
33 
34 caPubKey, caPrivKey, err := ed25519.GenerateKey(rand.Reader)
35 as.NoError(err)
36 
37 caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, caPubKey, caPrivKey)
38 as.NoError(err)
39 
40 return tls.Certificate{
41 Certificate: [][]byte{caBytes},
42 PrivateKey: caPrivKey,
43 }
44}
45 
46func TestSigning(t *testing.T) {
47 as := require.New(t)
48 logger := zaptest.NewLogger(t)
49 
50 cert := generateCA(as)
51 
52 server := &Server{
53 Logger: logger,
54 ClientCA: cert,
55 }
56 
57 clientPub, clientPriv, err := ed25519.GenerateKey(rand.Reader)
58 as.NoError(err)
59 req, err := CreateRequest(clientPriv)
60 as.NoError(err)
61 
62 resp, err := server.RequestCertificate(context.Background(), req)
63 as.NoError(err)
64 as.NotEmpty(resp.GetCertDer())
65 as.NotEmpty(resp.GetCertPem())
66 as.EqualValues(pki.MarshalCertificate(resp.GetCertDer()), resp.GetCertPem())
67 
68 ca, err := x509.ParseCertificate(cert.Certificate[0])
69 as.NoError(err)
70 caPool := x509.NewCertPool()
71 caPool.AddCert(ca)
72 verify := x509.VerifyOptions{
73 Roots: caPool,
74 KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
75 }
76 
77 clientCert, err := x509.ParseCertificate(resp.GetCertDer())
78 as.NoError(err)
79 
80 chains, err := clientCert.Verify(verify)
81 as.NoError(err)
82 c := chains[0][0]
83 as.EqualValues(clientPub, c.PublicKey)
84}
85 
86func TestRenewCertificate_Success(t *testing.T) {
87 as := require.New(t)
88 logger := zaptest.NewLogger(t)
89 
90 ca := generateCA(as)
91 
92 server := &Server{
93 Logger: logger,
94 ClientCA: ca,
95 }
96 
97 // Generate initial certificate
98 clientPub, clientPriv, err := ed25519.GenerateKey(rand.Reader)
99 as.NoError(err)
100 req, err := CreateRequest(clientPriv)
101 as.NoError(err)
102 
103 resp, err := server.RequestCertificate(context.Background(), req)
104 as.NoError(err)
105 as.NotEmpty(resp.GetCertDer())
106 
107 oldCert, err := x509.ParseCertificate(resp.GetCertDer())
108 as.NoError(err)
109 oldCN := oldCert.Subject.CommonName
110 
111 // Generate renewal request with same key
112 renewReq, err := CreateRenewalRequest(clientPriv, resp.GetCertDer())
113 as.NoError(err)
114 
115 renewResp, err := server.RenewCertificate(context.Background(), renewReq)
116 as.NoError(err)
117 as.NotEmpty(renewResp.GetCertDer())
118 as.NotEmpty(renewResp.GetCertPem())
119 as.EqualValues(pki.MarshalCertificate(renewResp.GetCertDer()), renewResp.GetCertPem())
120 
121 // Verify renewed cert
122 caCert, err := x509.ParseCertificate(ca.Certificate[0])
123 as.NoError(err)
124 caPool := x509.NewCertPool()
125 caPool.AddCert(caCert)
126 verify := x509.VerifyOptions{
127 Roots: caPool,
128 KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
129 }
130 
131 newCert, err := x509.ParseCertificate(renewResp.GetCertDer())
132 as.NoError(err)
133 
134 chains, err := newCert.Verify(verify)
135 as.NoError(err)
136 as.Len(chains, 1)
137 
138 // Verify CN is preserved
139 as.Equal(oldCN, newCert.Subject.CommonName)
140 // Verify public key is the same
141 as.EqualValues(clientPub, newCert.PublicKey)
142}
143 
144func TestRenewCertificate_InvalidCA(t *testing.T) {
145 as := require.New(t)
146 logger := zaptest.NewLogger(t)
147 
148 ca := generateCA(as)
149 differentCA := generateCA(as) // Different CA
150 
151 server := &Server{
152 Logger: logger,
153 ClientCA: ca,
154 }
155 
156 // Generate certificate with different CA
157 clientPub, clientPriv, err := ed25519.GenerateKey(rand.Reader)
158 as.NoError(err)
159 
160 // Create cert signed by different CA
161 certBytes, err := pki.GenerateCertificate(logger, differentCA, pki.IdentityRequest{
162 PublicKey: clientPub,
163 Subject: pki.MakeSubjectV2(12345, []byte("test")),
164 })
165 as.NoError(err)
166 
167 renewReq, err := CreateRenewalRequest(clientPriv, certBytes)
168 as.NoError(err)
169 
170 _, err = server.RenewCertificate(context.Background(), renewReq)
171 as.Error(err)
172 as.Contains(err.Error(), "permission_denied")
173}
174 
175func TestRenewCertificate_BadProof(t *testing.T) {
176 as := require.New(t)
177 logger := zaptest.NewLogger(t)
178 
179 ca := generateCA(as)
180 
181 server := &Server{
182 Logger: logger,
183 ClientCA: ca,
184 }
185 
186 // Generate initial certificate
187 _, clientPriv, err := ed25519.GenerateKey(rand.Reader)
188 as.NoError(err)
189 req, err := CreateRequest(clientPriv)
190 as.NoError(err)
191 
192 resp, err := server.RequestCertificate(context.Background(), req)
193 as.NoError(err)
194 
195 // Generate PoW with DIFFERENT key
196 _, differentPriv, err := ed25519.GenerateKey(rand.Reader)
197 as.NoError(err)
198 renewReq, err := CreateRenewalRequest(differentPriv, resp.GetCertDer())
199 as.NoError(err)
200 
201 _, err = server.RenewCertificate(context.Background(), renewReq)
202 as.Error(err)
203 as.Contains(err.Error(), "permission_denied")
204}
205 
206func TestRenewCertificate_V1Unsupported(t *testing.T) {
207 as := require.New(t)
208 logger := zaptest.NewLogger(t)
209 
210 ca := generateCA(as)
211 
212 server := &Server{
213 Logger: logger,
214 ClientCA: ca,
215 }
216 
217 // Generate v1 certificate
218 clientPub, clientPriv, err := ed25519.GenerateKey(rand.Reader)
219 as.NoError(err)
220 
221 v1Subject := pki.MakeSubjectV1(12345, "oldtoken")
222 certBytes, err := pki.GenerateCertificate(logger, ca, pki.IdentityRequest{
223 PublicKey: clientPub,
224 Subject: v1Subject,
225 })
226 as.NoError(err)
227 
228 renewReq, err := CreateRenewalRequest(clientPriv, certBytes)
229 as.NoError(err)
230 
231 _, err = server.RenewCertificate(context.Background(), renewReq)
232 as.Error(err)
233 as.Contains(err.Error(), "failed_precondition")
234 as.Contains(err.Error(), "v1 certificates cannot be renewed")
235}
236 
237func TestRenewCertificate_MissingCertDer(t *testing.T) {
238 as := require.New(t)
239 logger := zaptest.NewLogger(t)
240 
241 ca := generateCA(as)
242 
243 server := &Server{
244 Logger: logger,
245 ClientCA: ca,
246 }
247 
248 _, clientPriv, err := ed25519.GenerateKey(rand.Reader)
249 as.NoError(err)
250 
251 renewReq, err := CreateRenewalRequest(clientPriv, nil)
252 as.NoError(err)
253 
254 _, err = server.RenewCertificate(context.Background(), renewReq)
255 as.Error(err)
256 as.Contains(err.Error(), "current_cert_der")
257}