generate.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package cert
  2. import (
  3. "crypto/rand"
  4. "crypto/rsa"
  5. "crypto/x509"
  6. "crypto/x509/pkix"
  7. "encoding/pem"
  8. "errors"
  9. "math/big"
  10. "time"
  11. )
  12. var _ Generator = (*X509Generator)(nil)
  13. type Generator interface {
  14. CreateRootCa() ([]byte, []byte, error)
  15. CreateCert(dnsName string) ([]byte, []byte, error)
  16. InitRootCa(rootCa []byte, rootKey []byte) error
  17. }
  18. type X509Generator struct {
  19. rootCert *x509.Certificate
  20. rootRsaPrivate *rsa.PrivateKey
  21. subject pkix.Name
  22. }
  23. func NewX509Generator(subject pkix.Name) *X509Generator {
  24. return &X509Generator{
  25. subject: subject,
  26. }
  27. }
  28. func (cg *X509Generator) InitRootCa(rootCa []byte, rootKey []byte) error {
  29. var err error
  30. caBlock, _ := pem.Decode(rootCa)
  31. cg.rootCert, err = x509.ParseCertificate(caBlock.Bytes)
  32. if err != nil {
  33. return err
  34. }
  35. keyBlock, _ := pem.Decode(rootKey)
  36. cg.rootRsaPrivate, err = x509.ParsePKCS1PrivateKey(keyBlock.Bytes)
  37. if err != nil {
  38. return err
  39. }
  40. return nil
  41. }
  42. func (cg *X509Generator) CreateCert(dnsName string) ([]byte, []byte, error) {
  43. return cg.create(false, dnsName)
  44. }
  45. func (cg *X509Generator) CreateRootCa() ([]byte, []byte, error) {
  46. return cg.create(true, "")
  47. }
  48. func (cg *X509Generator) create(isRootCa bool, dnsName string) ([]byte, []byte, error) {
  49. serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
  50. serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
  51. template := &x509.Certificate{
  52. SerialNumber: serialNumber,
  53. Subject: cg.subject,
  54. NotBefore: time.Now(),
  55. NotAfter: time.Now().AddDate(3, 0, 0),
  56. BasicConstraintsValid: true,
  57. IsCA: false,
  58. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
  59. KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageDataEncipherment,
  60. DNSNames: []string{dnsName},
  61. }
  62. if isRootCa {
  63. template.IsCA = true
  64. template.KeyUsage |= x509.KeyUsageCertSign
  65. }
  66. priKey, err := rsa.GenerateKey(rand.Reader, 2048)
  67. if err != nil {
  68. return nil, nil, err
  69. }
  70. var ca []byte
  71. if !isRootCa {
  72. if cg.rootCert == nil || cg.rootRsaPrivate == nil {
  73. return nil, nil, errors.New("root ca is not exist")
  74. }
  75. ca, err = x509.CreateCertificate(rand.Reader, template, cg.rootCert, &priKey.PublicKey, cg.rootRsaPrivate)
  76. } else {
  77. ca, err = x509.CreateCertificate(rand.Reader, template, template, &priKey.PublicKey, priKey)
  78. }
  79. if err != nil {
  80. return nil, nil, err
  81. }
  82. caPem := &pem.Block{
  83. Type: "CERTIFICATE",
  84. Bytes: ca,
  85. }
  86. ca = pem.EncodeToMemory(caPem)
  87. buf := x509.MarshalPKCS1PrivateKey(priKey)
  88. keyPem := &pem.Block{
  89. Type: "PRIVATE KEY",
  90. Bytes: buf,
  91. }
  92. key := pem.EncodeToMemory(keyPem)
  93. return ca, key, nil
  94. }