go-cert-gen/internal/cert/client_cert.go

81 lines
1.9 KiB
Go

package cert
import (
"bytes"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"errors"
"fmt"
"time"
"gitlab.com/urkob/go-cert-gen/pkg/client"
)
type clientCert struct {
certPEM []byte
keyPEM []byte
}
func (c *clientCert) Key() []byte {
return c.keyPEM
}
func (c *clientCert) PEM() []byte {
return c.certPEM
}
func newClientCert(config *client.ClientCertConfig, rootCA *x509.Certificate, rootKeyPEM []byte) ([]byte, []byte, error) {
template := &x509.Certificate{
SerialNumber: config.Serial,
Subject: pkix.Name{
Organization: []string{config.Subject.Organization},
Country: []string{config.Subject.Country},
Province: []string{config.Subject.Province},
Locality: []string{config.Subject.Locality},
StreetAddress: []string{config.Subject.StreetAddress},
PostalCode: []string{config.Subject.PostalCode},
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(config.Duration),
SubjectKeyId: config.SubjectKeyId,
ExtKeyUsage: config.ExtKeyUsage,
KeyUsage: config.KeyUsage,
}
block, _ := pem.Decode(rootKeyPEM)
if block == nil {
return nil, nil, errors.New("pem.Decode")
}
caPrivKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, nil, fmt.Errorf("x509.ParsePKCS8PrivateKey: %s", err)
}
priv, err := newPrivateKey()
if err != nil {
return nil, nil, fmt.Errorf("newPrivateKey: %s", err)
}
der, err := x509.CreateCertificate(rand.Reader, template, rootCA, &priv.PublicKey, caPrivKey)
if err != nil {
return nil, nil, fmt.Errorf("x509.CreateCertificate: %s", err)
}
out := &bytes.Buffer{}
err = pem.Encode(out, &pem.Block{Type: CERTIFICATE, Bytes: der})
if err != nil {
return nil, nil, fmt.Errorf("pem.Encode: %s", err)
}
certPEM := out.Bytes()
keyPEM, err := encodePrivateKey(priv)
if err != nil {
return nil, nil, fmt.Errorf("encodePrivateKey: %s", err)
}
return certPEM, keyPEM, nil
}