ssl.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package tools
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "crypto/rsa"
  6. "crypto/x509"
  7. "crypto/x509/pkix"
  8. "encoding/pem"
  9. "fmt"
  10. "math/big"
  11. "os"
  12. "time"
  13. )
  14. func SSL() *ssl {
  15. return &ssl{}
  16. }
  17. type (
  18. ssl struct {
  19. }
  20. sslcert struct {
  21. privateKey *rsa.PrivateKey
  22. Template x509.Certificate
  23. }
  24. )
  25. func (t *ssl) Cert(cn string) (res *sslcert) {
  26. res = &sslcert{}
  27. var err error
  28. res.privateKey, err = rsa.GenerateKey(rand.Reader, 4096)
  29. if err != nil {
  30. log.Write([]byte(fmt.Sprintf("failed to generate private key: %w", err)))
  31. return
  32. }
  33. serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
  34. serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
  35. if err != nil {
  36. log.Write([]byte(fmt.Sprintf("failed to generate serial number: %w", err)))
  37. return
  38. }
  39. res.Template = x509.Certificate{
  40. SerialNumber: serialNumber,
  41. Subject: pkix.Name{
  42. // Organization: []string{org},
  43. CommonName: cn, // Essential for browsers/clients to trust the cert
  44. },
  45. NotBefore: time.Now(),
  46. NotAfter: time.Now().Add(365 * 24 * time.Hour), // Valid for 1 year
  47. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
  48. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
  49. BasicConstraintsValid: true,
  50. IsCA: true, // Mark as a CA to sign other certs if needed
  51. DNSNames: []string{cn},
  52. }
  53. return
  54. }
  55. func (res *sslcert) WriteCSR(file string) error {
  56. csrTemplate := x509.CertificateRequest{
  57. Subject: res.Template.Subject,
  58. DNSNames: res.Template.DNSNames,
  59. }
  60. csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &csrTemplate, res.privateKey)
  61. if err != nil {
  62. return fmt.Errorf("Failed to create certificate request: %v", err)
  63. }
  64. csrPEM := pem.EncodeToMemory(&pem.Block{
  65. Type: "CERTIFICATE REQUEST",
  66. Bytes: csrBytes,
  67. })
  68. return os.WriteFile(file, csrPEM, 0644)
  69. }
  70. func (res *sslcert) WritePEMs(key, crt string) error {
  71. certBytes, err := x509.CreateCertificate(rand.Reader, &res.Template, &res.Template, res.privateKey.PublicKey, res.privateKey)
  72. if err != nil {
  73. return fmt.Errorf("failed to create certificate: %w", err)
  74. }
  75. certPEM := new(bytes.Buffer)
  76. pem.Encode(certPEM, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
  77. keyPEM := new(bytes.Buffer)
  78. pem.Encode(keyPEM, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(res.privateKey)})
  79. if err := os.WriteFile(crt, certPEM.Bytes(), 0644); err != nil {
  80. return fmt.Errorf("failed to write cert.pem: %w", err)
  81. }
  82. if err := os.WriteFile(key, keyPEM.Bytes(), 0600); err != nil {
  83. return fmt.Errorf("failed to write key.pem: %w", err)
  84. }
  85. return nil
  86. }