github.com/zmap/zcrypto@v0.0.0-20240512203510-0fef58d9a9db/tls/generate_cert.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build ignore 6 // +build ignore 7 8 // Generate a self-signed X.509 certificate for a TLS server. Outputs to 9 // 'cert.pem' and 'key.pem' and will overwrite existing files. 10 11 package main 12 13 import ( 14 "crypto/rand" 15 "crypto/rsa" 16 17 "github.com/zmap/zcrypto/x509" 18 "github.com/zmap/zcrypto/x509/pkix" 19 20 "encoding/pem" 21 "flag" 22 "fmt" 23 "log" 24 "math/big" 25 "net" 26 "os" 27 "strings" 28 "time" 29 ) 30 31 var ( 32 host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for") 33 validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011") 34 validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for") 35 isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority") 36 rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate") 37 ) 38 39 func main() { 40 flag.Parse() 41 42 if len(*host) == 0 { 43 log.Fatalf("Missing required --host parameter") 44 } 45 46 priv, err := rsa.GenerateKey(rand.Reader, *rsaBits) 47 if err != nil { 48 log.Fatalf("failed to generate private key: %s", err) 49 } 50 51 var notBefore time.Time 52 if len(*validFrom) == 0 { 53 notBefore = time.Now() 54 } else { 55 notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom) 56 if err != nil { 57 fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err) 58 os.Exit(1) 59 } 60 } 61 62 notAfter := notBefore.Add(*validFor) 63 64 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 65 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 66 if err != nil { 67 log.Fatalf("failed to generate serial number: %s", err) 68 } 69 70 template := x509.Certificate{ 71 SerialNumber: serialNumber, 72 Subject: pkix.Name{ 73 Organization: []string{"Acme Co"}, 74 }, 75 NotBefore: notBefore, 76 NotAfter: notAfter, 77 78 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 79 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 80 BasicConstraintsValid: true, 81 } 82 83 hosts := strings.Split(*host, ",") 84 for _, h := range hosts { 85 if ip := net.ParseIP(h); ip != nil { 86 template.IPAddresses = append(template.IPAddresses, ip) 87 } else { 88 template.DNSNames = append(template.DNSNames, h) 89 } 90 } 91 92 if *isCA { 93 template.IsCA = true 94 template.KeyUsage |= x509.KeyUsageCertSign 95 } 96 97 derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) 98 if err != nil { 99 log.Fatalf("Failed to create certificate: %s", err) 100 } 101 102 certOut, err := os.Create("cert.pem") 103 if err != nil { 104 log.Fatalf("failed to open cert.pem for writing: %s", err) 105 } 106 pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) 107 certOut.Close() 108 log.Print("written cert.pem\n") 109 110 keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 111 if err != nil { 112 log.Print("failed to open key.pem for writing:", err) 113 return 114 } 115 pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) 116 keyOut.Close() 117 log.Print("written key.pem\n") 118 }