github.com/ergo-services/ergo@v1.999.224/lib/cert.go (about) 1 package lib 2 3 import ( 4 "bytes" 5 "crypto/ecdsa" 6 "crypto/elliptic" 7 "crypto/rand" 8 "crypto/tls" 9 "crypto/x509" 10 "crypto/x509/pkix" 11 "encoding/pem" 12 "math/big" 13 "net" 14 "sync" 15 "time" 16 ) 17 18 // GenerateSelfSignedCert 19 func GenerateSelfSignedCert(org string, hosts ...string) (tls.Certificate, error) { 20 var cert = tls.Certificate{} 21 certPrivKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) 22 if err != nil { 23 return cert, err 24 } 25 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 26 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 27 if err != nil { 28 return cert, err 29 } 30 31 template := x509.Certificate{ 32 SerialNumber: serialNumber, 33 Subject: pkix.Name{ 34 Organization: []string{org}, 35 }, 36 NotBefore: time.Now(), 37 NotAfter: time.Now().Add(time.Hour * 24 * 365), 38 IsCA: true, 39 40 KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature, 41 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 42 BasicConstraintsValid: true, 43 } 44 45 for _, h := range hosts { 46 if ip := net.ParseIP(h); ip != nil { 47 template.IPAddresses = append(template.IPAddresses, ip) 48 } else { 49 template.DNSNames = append(template.DNSNames, h) 50 } 51 } 52 53 certBytes, err1 := x509.CreateCertificate(rand.Reader, &template, &template, 54 &certPrivKey.PublicKey, certPrivKey) 55 if err1 != nil { 56 return cert, err1 57 } 58 59 certPEM := new(bytes.Buffer) 60 pem.Encode(certPEM, &pem.Block{ 61 Type: "CERTIFICATE", 62 Bytes: certBytes, 63 }) 64 65 certPrivKeyPEM := new(bytes.Buffer) 66 x509Encoded, _ := x509.MarshalECPrivateKey(certPrivKey) 67 pem.Encode(certPrivKeyPEM, &pem.Block{ 68 Type: "RSA PRIVATE KEY", 69 Bytes: x509Encoded, 70 }) 71 72 return tls.X509KeyPair(certPEM.Bytes(), certPrivKeyPEM.Bytes()) 73 } 74 75 type CertUpdater struct { 76 sync.RWMutex 77 cert *tls.Certificate 78 } 79 80 func CreateCertUpdater(cert tls.Certificate) *CertUpdater { 81 return &CertUpdater{ 82 cert: &cert, 83 } 84 } 85 86 func (cu *CertUpdater) Update(cert tls.Certificate) { 87 cu.Lock() 88 defer cu.Unlock() 89 90 cu.cert = &cert 91 } 92 93 func (cu *CertUpdater) GetCertificateFunc() func(*tls.ClientHelloInfo) (*tls.Certificate, error) { 94 return func(ch *tls.ClientHelloInfo) (*tls.Certificate, error) { 95 cu.RLock() 96 defer cu.RUnlock() 97 return cu.cert, nil 98 } 99 }