@@ -17,8 +17,8 @@ limitations under the License.
1717package signer
1818
1919import (
20+ "context"
2021 "crypto"
21- "crypto/ecdsa"
2222 "crypto/elliptic"
2323 "crypto/rand"
2424 "crypto/x509"
@@ -30,6 +30,8 @@ import (
3030
3131 "github.com/pkg/errors"
3232 "github.com/sigstore/sigstore/pkg/signature"
33+ "github.com/sigstore/sigstore/pkg/signature/kms/gcp"
34+ "github.com/sigstore/sigstore/pkg/signature/options"
3335)
3436
3537const MemoryScheme = "memory"
@@ -39,33 +41,48 @@ type Memory struct {
3941 signature.ECDSASignerVerifier
4042}
4143
42- // create a self-signed CA and generate a timestamping certificate to rekor
43- func NewTimestampingCertWithSelfSignedCA (pub crypto.PublicKey ) ([]* x509.Certificate , error ) {
44- // generate self-signed CA
45- caPrivKey , err := ecdsa .GenerateKey (elliptic .P256 (), rand .Reader )
44+ // Generate a timestamping certificate for pub using the signer. The chain must verify the signer's public key if provided.
45+ // Otherwise, a self-signed root CA will be generated.
46+ func NewTimestampingCertWithChain (ctx context.Context , pub crypto.PublicKey , signer signature.Signer , chain []* x509.Certificate ) ([]* x509.Certificate , error ) {
47+ // Get the signer's (rekor's) public key
48+ signerPubKey , err := signer .PublicKey (options .WithContext (ctx ))
4649 if err != nil {
47- return nil , errors . Wrap ( err , "generating private key" )
50+ return nil , err
4851 }
49- ca := & x509.Certificate {
50- SerialNumber : big .NewInt (2019 ),
51- Subject : pkix.Name {
52- Organization : []string {"Root CA Test" },
53- Country : []string {"US" },
54- Province : []string {"" },
55- Locality : []string {"San Francisco" },
56- StreetAddress : []string {"Golden Gate Bridge" },
57- PostalCode : []string {"94016" },
58- },
59- NotBefore : time .Now (),
60- NotAfter : time .Now ().AddDate (10 , 0 , 0 ),
61- IsCA : true ,
62- KeyUsage : x509 .KeyUsageDigitalSignature | x509 .KeyUsageContentCommitment | x509 .KeyUsageCertSign ,
63- BasicConstraintsValid : true ,
52+
53+ // If the signer is not in-memory, retrieve the crypto.Signer
54+ var cryptoSigner crypto.Signer
55+ if s , ok := signer .(* gcp.SignerVerifier ); ok {
56+ if cryptoSigner , _ , err = s .CryptoSigner (ctx , func (err error ) {}); err != nil {
57+ return nil , errors .Wrap (err , "getting kms signer" )
58+ }
59+ } else {
60+ cryptoSigner = signer .(crypto.Signer )
6461 }
65- caBytes , err := x509 .CreateCertificate (rand .Reader , ca , ca , & caPrivKey .PublicKey , caPrivKey )
66- if err != nil {
67- return nil , err
62+
63+ if len (chain ) == 0 {
64+ // Generate an in-memory self-signed root CA.
65+ ca := & x509.Certificate {
66+ SerialNumber : big .NewInt (2019 ),
67+ Subject : pkix.Name {
68+ Organization : []string {"rekor in-memory root CA" },
69+ },
70+ NotBefore : time .Now (),
71+ NotAfter : time .Now ().AddDate (10 , 0 , 0 ),
72+ IsCA : true ,
73+ KeyUsage : x509 .KeyUsageDigitalSignature | x509 .KeyUsageContentCommitment | x509 .KeyUsageCertSign ,
74+ BasicConstraintsValid : true ,
75+ }
76+ caBytes , err := x509 .CreateCertificate (rand .Reader , ca , ca , signerPubKey , cryptoSigner )
77+ if err != nil {
78+ return nil , errors .Wrap (err , "creating self-signed CA" )
79+ }
80+ chain , err = x509 .ParseCertificates (caBytes )
81+ if err != nil {
82+ return nil , err
83+ }
6884 }
85+
6986 timestampExt , err := asn1 .Marshal ([]asn1.ObjectIdentifier {{1 , 3 , 6 , 1 , 5 , 5 , 7 , 3 , 8 }})
7087 if err != nil {
7188 return nil , err
@@ -74,12 +91,7 @@ func NewTimestampingCertWithSelfSignedCA(pub crypto.PublicKey) ([]*x509.Certific
7491 cert := & x509.Certificate {
7592 SerialNumber : big .NewInt (1658 ),
7693 Subject : pkix.Name {
77- Organization : []string {"Rekor Test" },
78- Country : []string {"US" },
79- Province : []string {"" },
80- Locality : []string {"San Francisco" },
81- StreetAddress : []string {"Golden Gate Bridge" },
82- PostalCode : []string {"94016" },
94+ Organization : []string {"Rekor Timestamping Cert" },
8395 },
8496 IPAddresses : []net.IP {net .IPv4 (127 , 0 , 0 , 1 ), net .IPv6loopback },
8597 NotBefore : time .Now (),
@@ -97,11 +109,33 @@ func NewTimestampingCertWithSelfSignedCA(pub crypto.PublicKey) ([]*x509.Certific
97109 },
98110 BasicConstraintsValid : true ,
99111 }
100- certBytes , err := x509 .CreateCertificate (rand .Reader , cert , ca , pub .(* ecdsa.PublicKey ), caPrivKey )
112+
113+ // Create the certificate
114+ certBytes , err := x509 .CreateCertificate (rand .Reader , cert , chain [0 ], pub , cryptoSigner )
101115 if err != nil {
116+ return nil , errors .Wrap (err , "creating tsa certificate" )
117+ }
118+ tsaCert , err := x509 .ParseCertificates (certBytes )
119+ if err != nil {
120+ return nil , err
121+ }
122+
123+ // Verify and return the certificate chain
124+ root := x509 .NewCertPool ()
125+ root .AddCert (chain [len (chain )- 1 ])
126+ intermediates := x509 .NewCertPool ()
127+ for _ , intermediate := range chain [:len (chain )- 1 ] {
128+ intermediates .AddCert (intermediate )
129+ }
130+ verifyOptions := x509.VerifyOptions {
131+ Roots : root ,
132+ Intermediates : intermediates ,
133+ KeyUsages : []x509.ExtKeyUsage {x509 .ExtKeyUsageTimeStamping },
134+ }
135+ if _ , err = tsaCert [0 ].Verify (verifyOptions ); err != nil {
102136 return nil , err
103137 }
104- return x509 . ParseCertificates ( append (certBytes , caBytes ... ))
138+ return append (tsaCert , chain ... ), nil
105139}
106140
107141func NewMemory () (* Memory , error ) {
0 commit comments