mkcert.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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. "net"
  11. "time"
  12. M "github.com/sagernet/sing/common/metadata"
  13. )
  14. func GenerateKeyPair(parent *x509.Certificate, parentKey any, timeFunc func() time.Time, serverName string) (*tls.Certificate, error) {
  15. if timeFunc == nil {
  16. timeFunc = time.Now
  17. }
  18. privateKeyPem, publicKeyPem, err := GenerateCertificate(parent, parentKey, timeFunc, serverName, timeFunc().Add(time.Hour))
  19. if err != nil {
  20. return nil, err
  21. }
  22. certificate, err := tls.X509KeyPair(publicKeyPem, privateKeyPem)
  23. if err != nil {
  24. return nil, err
  25. }
  26. return &certificate, err
  27. }
  28. func GenerateCertificate(parent *x509.Certificate, parentKey any, timeFunc func() time.Time, serverName string, expire time.Time) (privateKeyPem []byte, publicKeyPem []byte, err error) {
  29. key, err := rsa.GenerateKey(rand.Reader, 2048)
  30. if err != nil {
  31. return
  32. }
  33. serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
  34. if err != nil {
  35. return
  36. }
  37. var template *x509.Certificate
  38. if serverAddress := M.ParseAddr(serverName); serverAddress.IsValid() {
  39. template = &x509.Certificate{
  40. SerialNumber: serialNumber,
  41. IPAddresses: []net.IP{serverAddress.AsSlice()},
  42. NotBefore: timeFunc().Add(time.Hour * -1),
  43. NotAfter: expire,
  44. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  45. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  46. BasicConstraintsValid: true,
  47. }
  48. } else {
  49. template = &x509.Certificate{
  50. SerialNumber: serialNumber,
  51. NotBefore: timeFunc().Add(time.Hour * -1),
  52. NotAfter: expire,
  53. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  54. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  55. BasicConstraintsValid: true,
  56. Subject: pkix.Name{
  57. CommonName: serverName,
  58. },
  59. DNSNames: []string{serverName},
  60. }
  61. }
  62. if parent == nil {
  63. parent = template
  64. parentKey = key
  65. }
  66. publicDer, err := x509.CreateCertificate(rand.Reader, template, parent, key.Public(), parentKey)
  67. if err != nil {
  68. return
  69. }
  70. privateDer, err := x509.MarshalPKCS8PrivateKey(key)
  71. if err != nil {
  72. return
  73. }
  74. publicKeyPem = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: publicDer})
  75. privateKeyPem = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privateDer})
  76. return
  77. }