Files
shhh/internal/clis/hmpki/generate_ca.go
T

91 lines
2.1 KiB
Go

package hmpki
import (
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"errors"
"math"
"math/big"
"path"
"time"
"git.handmadecities.com/HMC/shhh/pkg/pki"
"github.com/spf13/cobra"
)
func init() {
generateCmd.AddCommand(generateCACmd)
generateCACmd.Flags().StringVar(
&CommonName,
"common-name",
"",
"Common Name for the CA",
)
generateCACmd.MarkFlagRequired("common-name")
}
var generateCACmd = &cobra.Command{
Use: "ca",
Short: "Generate a Certificate Authority",
RunE: func(cmd *cobra.Command, args []string) error {
// Private key for the ca.
key := pki.GenerateKey()
// Cryptographically random 64bit number as the serial.
sn, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
if err != nil {
return errors.New("Could not generate a ca serial number")
}
caTmpl := &x509.Certificate{
SerialNumber: sn,
Subject: pkix.Name{
// TODO: Accept common name as a flag.
CommonName: CommonName,
},
// Valid starting now and for 10 years.
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(10, 0, 0),
// This cert is a CA.
IsCA: true,
// No intermeddiate CAs, just one root that can issue leaf certs.
MaxPathLen: 0,
MaxPathLenZero: true,
// Disambiguate `IsCA` and path len settings from their zero value.
BasicConstraintsValid: true,
// Only allow to sign new certs, and cert revokation lists.
// Can't be used as a server or client cert itself.
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
}
caBytes, err := x509.CreateCertificate(
rand.Reader,
// Same template and parent, i.e. self-signed.
caTmpl,
caTmpl,
&key.PublicKey,
key,
)
caPEMBytes := pem.EncodeToMemory(&pem.Block{
Type: pki.PEMTypeCertificate,
Bytes: caBytes,
})
// Write ca to disk.
cafn := path.Join(OutDir, Name+"_ca.crt")
err = createFileWith(cafn, caPEMBytes, pki.CertFilePerms)
if err != nil {
return err
}
// Write private key to disk.
keyfn := path.Join(OutDir, Name+"_ca.key")
err = createFileWith(keyfn, pki.MarshalKeyToPEM(key), pki.PrivateKeyFilePerms)
if err != nil {
return err
}
return nil
},
}