generatecert.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. // Generate a self-signed X.509 certificate for a TLS server. Outputs to
  5. // 'cert.pem' and 'key.pem' and will overwrite existing files.
  6. package crypt
  7. import (
  8. "crypto/ecdsa"
  9. "crypto/ed25519"
  10. "crypto/elliptic"
  11. "crypto/rand"
  12. "crypto/rsa"
  13. "crypto/tls"
  14. "crypto/x509"
  15. "crypto/x509/pkix"
  16. "encoding/pem"
  17. "log"
  18. "math/big"
  19. "net"
  20. "strings"
  21. "time"
  22. )
  23. type GenerateCertificate struct {
  24. Organization string
  25. Host string
  26. ValidFrom string
  27. ValidFor time.Duration
  28. IsCA bool
  29. RSABits int
  30. EcdsaCurve string
  31. Ed25519Key bool
  32. }
  33. func (gc *GenerateCertificate) publicKey(priv interface{}) interface{} {
  34. switch k := priv.(type) {
  35. case *rsa.PrivateKey:
  36. return &k.PublicKey
  37. case *ecdsa.PrivateKey:
  38. return &k.PublicKey
  39. case ed25519.PrivateKey:
  40. return k.Public().(ed25519.PublicKey)
  41. default:
  42. return nil
  43. }
  44. }
  45. func (gc *GenerateCertificate) GenerateTLSConfig() (*tls.Config, error) {
  46. var priv interface{}
  47. var err error
  48. switch gc.EcdsaCurve {
  49. case "":
  50. if gc.Ed25519Key {
  51. _, priv, err = ed25519.GenerateKey(rand.Reader)
  52. } else {
  53. priv, err = rsa.GenerateKey(rand.Reader, gc.RSABits)
  54. }
  55. case "P224":
  56. priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
  57. case "P256":
  58. priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  59. case "P384":
  60. priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
  61. case "P521":
  62. priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
  63. default:
  64. log.Fatalf("Unrecognized elliptic curve: %q", gc.EcdsaCurve)
  65. return nil, err
  66. }
  67. if err != nil {
  68. log.Fatalf("Failed to generate private key: %v", err)
  69. return nil, err
  70. }
  71. var notBefore time.Time
  72. if len(gc.ValidFrom) == 0 {
  73. notBefore = time.Now()
  74. } else {
  75. notBefore, err = time.Parse("Jan 2 15:04:05 2006", gc.ValidFrom)
  76. if err != nil {
  77. log.Fatalf("Failed to parse creation date: %v", err)
  78. return nil, err
  79. }
  80. }
  81. notAfter := notBefore.Add(gc.ValidFor)
  82. serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
  83. serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
  84. if err != nil {
  85. log.Fatalf("Failed to generate serial number: %v", err)
  86. return nil, err
  87. }
  88. template := x509.Certificate{
  89. SerialNumber: serialNumber,
  90. Subject: pkix.Name{
  91. Organization: []string{gc.Organization},
  92. },
  93. NotBefore: notBefore,
  94. NotAfter: notAfter,
  95. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  96. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  97. BasicConstraintsValid: true,
  98. }
  99. hosts := strings.Split(gc.Host, ",")
  100. for _, h := range hosts {
  101. if ip := net.ParseIP(h); ip != nil {
  102. template.IPAddresses = append(template.IPAddresses, ip)
  103. } else {
  104. template.DNSNames = append(template.DNSNames, h)
  105. }
  106. }
  107. if gc.IsCA {
  108. template.IsCA = true
  109. template.KeyUsage |= x509.KeyUsageCertSign
  110. }
  111. derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, gc.publicKey(priv), priv)
  112. if err != nil {
  113. log.Fatalf("Failed to create certificate: %v", err)
  114. return nil, err
  115. }
  116. privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
  117. if err != nil {
  118. log.Fatalf("Unable to marshal private key: %v", err)
  119. return nil, err
  120. }
  121. keyPEM := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privBytes})
  122. certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
  123. tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
  124. return &tls.Config{Certificates: []tls.Certificate{tlsCert}}, nil
  125. }