package crt import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "crypto/x509/pkix" "database/sql" "fmt" "log" "math/big" "time" "github.com/jasinco/crtman/internal/cli" "github.com/jasinco/crtman/internal/store" ) func IssueRoot(config cli.CA_CFG) { log.Printf("CA: Org: %s, FQDN: %s\n", config.Org, config.FQDN) rootca := x509.Certificate{ IsCA: true, Version: 1, KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageOCSPSigning}, Subject: pkix.Name{ Country: []string{"Taiwan"}, Organization: []string{config.Org}, CommonName: config.FQDN, }, NotBefore: time.Now(), BasicConstraintsValid: true, SerialNumber: big.NewInt(0), } privkey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { log.Fatal(err) } crt, err := x509.CreateCertificate(rand.Reader, &rootca, &rootca, &privkey.PublicKey, privkey) if err != nil { log.Fatal("can't create x509 ca, ", err) } // privkey_bytes, err := x509.MarshalECPrivateKey(privkey) // if err != nil { // log.Fatal("can't create ecdsa key encoded, ", err) // } store.RootCA = crt store.RootCAKey = privkey } // csr is a DER csr func IssueCert(csr []byte) sql.Null[[]byte] { req, err := x509.ParseCertificateRequest(csr) if err != nil { return sql.Null[[]byte]{Valid: false} } if req.CheckSignature() != nil { return sql.Null[[]byte]{Valid: false} } store.SerialLock.Lock() defer store.SerialLock.Unlock() cert := x509.Certificate{ Subject: req.Subject, PublicKey: req.PublicKey, PublicKeyAlgorithm: req.PublicKeyAlgorithm, NotBefore: time.Now(), NotAfter: time.Now().Add(time.Hour * 24 * 720), KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, IsCA: false, BasicConstraintsValid: true, DNSNames: req.DNSNames, IPAddresses: req.IPAddresses, SerialNumber: &store.Serial, OCSPServer: []string{fmt.Sprintf("https://%s/api/ocsp", cli.Outbound)}, } ca, err := x509.ParseCertificate(store.RootCA) if err != nil { log.Println(err) return sql.Null[[]byte]{Valid: false} } signed, err := x509.CreateCertificate(rand.Reader, &cert, ca, req.PublicKey, store.RootCAKey) if err != nil { log.Println(err) return sql.Null[[]byte]{Valid: false} } store.Serial.Add(&store.Serial, big.NewInt(1)) return sql.Null[[]byte]{Valid: true, V: signed} }