mkcert.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package tls
  2. import (
  3. "crypto/rand"
  4. "crypto/rsa"
  5. "crypto/tls"
  6. "crypto/x509"
  7. "crypto/x509/pkix"
  8. "encoding/pem"
  9. "math/big"
  10. "time"
  11. )
  12. func GenerateKeyPair(parent *x509.Certificate, parentKey any, timeFunc func() time.Time, serverName string) (*tls.Certificate, error) {
  13. if timeFunc == nil {
  14. timeFunc = time.Now
  15. }
  16. privateKeyPem, publicKeyPem, err := GenerateCertificate(parent, parentKey, timeFunc, serverName, timeFunc().Add(time.Hour))
  17. if err != nil {
  18. return nil, err
  19. }
  20. certificate, err := tls.X509KeyPair(publicKeyPem, privateKeyPem)
  21. if err != nil {
  22. return nil, err
  23. }
  24. return &certificate, err
  25. }
  26. func GenerateCertificate(parent *x509.Certificate, parentKey any, timeFunc func() time.Time, serverName string, expire time.Time) (privateKeyPem []byte, publicKeyPem []byte, err error) {
  27. key, err := rsa.GenerateKey(rand.Reader, 2048)
  28. if err != nil {
  29. return
  30. }
  31. serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
  32. if err != nil {
  33. return
  34. }
  35. template := &x509.Certificate{
  36. SerialNumber: serialNumber,
  37. NotBefore: timeFunc().Add(time.Hour * -1),
  38. NotAfter: expire,
  39. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  40. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  41. BasicConstraintsValid: true,
  42. Subject: pkix.Name{
  43. CommonName: serverName,
  44. },
  45. DNSNames: []string{serverName},
  46. }
  47. if parent == nil {
  48. parent = template
  49. parentKey = key
  50. }
  51. publicDer, err := x509.CreateCertificate(rand.Reader, template, parent, key.Public(), parentKey)
  52. if err != nil {
  53. return
  54. }
  55. privateDer, err := x509.MarshalPKCS8PrivateKey(key)
  56. if err != nil {
  57. return
  58. }
  59. publicKeyPem = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: publicDer})
  60. privateKeyPem = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privateDer})
  61. return
  62. }