1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package signer
16
17 import (
18 "crypto"
19 "crypto/ecdsa"
20 "crypto/elliptic"
21 "crypto/rand"
22 "crypto/x509"
23 "crypto/x509/pkix"
24 "encoding/asn1"
25 "fmt"
26 "time"
27
28 "github.com/pkg/errors"
29 "github.com/sigstore/sigstore/pkg/cryptoutils"
30 tsx509 "github.com/sigstore/timestamp-authority/pkg/x509"
31 )
32
33
34 func NewTimestampingCertWithChain(signer crypto.Signer) ([]*x509.Certificate, error) {
35 now := time.Now()
36
37
38 rootPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
39 if err != nil {
40 return nil, fmt.Errorf("generating in-memory root key")
41 }
42 sn, err := cryptoutils.GenerateSerialNumber()
43 if err != nil {
44 return nil, fmt.Errorf("generating root serial number: %w", err)
45 }
46 rootCA := &x509.Certificate{
47 SerialNumber: sn,
48 Subject: pkix.Name{
49 CommonName: "Test TSA Root",
50 Organization: []string{"local"},
51 },
52 NotBefore: now.Add(-5 * time.Minute),
53 NotAfter: now.AddDate(10, 0, 0),
54 IsCA: true,
55 BasicConstraintsValid: true,
56 KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
57 }
58 rootCACertDER, err := x509.CreateCertificate(rand.Reader, rootCA, rootCA, rootPriv.Public(), rootPriv)
59 if err != nil {
60 return nil, fmt.Errorf("creating self-signed root CA: %w", err)
61 }
62 rootCACert, err := x509.ParseCertificate(rootCACertDER)
63 if err != nil {
64 return nil, fmt.Errorf("parsing root CA certificate: %w", err)
65 }
66
67
68 sn, err = cryptoutils.GenerateSerialNumber()
69 if err != nil {
70 return nil, fmt.Errorf("generating subordinate serial number: %w", err)
71 }
72 subPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
73 if err != nil {
74 return nil, fmt.Errorf("generating in-memory subordinate key")
75 }
76 subCA := &x509.Certificate{
77 SerialNumber: sn,
78 Subject: pkix.Name{
79 CommonName: "Test TSA Intermediate",
80 Organization: []string{"local"},
81 },
82 NotBefore: now.Add(-5 * time.Minute),
83 NotAfter: now.AddDate(10, 0, 0),
84 KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
85 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageTimeStamping},
86 BasicConstraintsValid: true,
87 IsCA: true,
88 }
89 subCACertDER, err := x509.CreateCertificate(rand.Reader, subCA, rootCACert, subPriv.Public(), rootPriv)
90 if err != nil {
91 return nil, fmt.Errorf("creating self-signed subordinate CA: %w", err)
92 }
93 subCACert, err := x509.ParseCertificate(subCACertDER)
94 if err != nil {
95 return nil, fmt.Errorf("parsing subordinate CA certificate: %w", err)
96 }
97
98
99 sn, err = cryptoutils.GenerateSerialNumber()
100 if err != nil {
101 return nil, fmt.Errorf("generating leaf serial number: %w", err)
102 }
103 timestampExt, err := asn1.Marshal([]asn1.ObjectIdentifier{tsx509.EKUTimestampingOID})
104 if err != nil {
105 return nil, err
106 }
107
108 skid, err := cryptoutils.SKID(signer.Public())
109 if err != nil {
110 return nil, err
111 }
112
113 cert := &x509.Certificate{
114 SerialNumber: sn,
115 Subject: pkix.Name{
116 CommonName: "Test TSA Timestamping",
117 Organization: []string{"local"},
118 },
119 SubjectKeyId: skid,
120 NotBefore: now.Add(-3 * time.Minute),
121 NotAfter: now.AddDate(9, 0, 0),
122 IsCA: false,
123 KeyUsage: x509.KeyUsageDigitalSignature,
124
125 ExtraExtensions: []pkix.Extension{
126 {
127 Id: tsx509.EKUOID,
128 Critical: true,
129 Value: timestampExt,
130 },
131 },
132 }
133 certDER, err := x509.CreateCertificate(rand.Reader, cert, subCACert, signer.Public(), subPriv)
134 if err != nil {
135 return nil, errors.Wrap(err, "creating tsa certificate")
136 }
137 tsaCert, err := x509.ParseCertificate(certDER)
138 if err != nil {
139 return nil, err
140 }
141
142
143 root := x509.NewCertPool()
144 root.AddCert(rootCACert)
145 intermediate := x509.NewCertPool()
146 intermediate.AddCert(subCACert)
147 verifyOptions := x509.VerifyOptions{
148 Roots: root,
149 Intermediates: intermediate,
150 KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageTimeStamping},
151 }
152 if _, err = tsaCert.Verify(verifyOptions); err != nil {
153 return nil, err
154 }
155
156 return []*x509.Certificate{tsaCert, subCACert, rootCACert}, nil
157 }
158
View as plain text