github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/util/tls/tls.go (about)

     1  // Licensed under the Apache License, Version 2.0 (the "License");
     2  // you may not use this file except in compliance with the License.
     3  // You may obtain a copy of the License at
     4  //
     5  //     https://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS,
     9  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  // See the License for the specific language governing permissions and
    11  // limitations under the License.
    12  //
    13  // Original source: github.com/micro/go-micro/v3/util/tls/tls.go
    14  
    15  package tls
    16  
    17  import (
    18  	"bytes"
    19  	"crypto/ecdsa"
    20  	"crypto/elliptic"
    21  	"crypto/rand"
    22  	"crypto/tls"
    23  	"crypto/x509"
    24  	"crypto/x509/pkix"
    25  	"encoding/pem"
    26  	"math/big"
    27  	"net"
    28  	"time"
    29  )
    30  
    31  func Certificate(host ...string) (tls.Certificate, error) {
    32  	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    33  	if err != nil {
    34  		return tls.Certificate{}, err
    35  	}
    36  
    37  	notBefore := time.Now()
    38  	notAfter := notBefore.Add(time.Hour * 24 * 365)
    39  
    40  	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
    41  	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
    42  	if err != nil {
    43  		return tls.Certificate{}, err
    44  	}
    45  
    46  	template := x509.Certificate{
    47  		SerialNumber: serialNumber,
    48  		Subject: pkix.Name{
    49  			Organization: []string{"Acme Co"},
    50  		},
    51  		NotBefore: notBefore,
    52  		NotAfter:  notAfter,
    53  
    54  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
    55  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
    56  		BasicConstraintsValid: true,
    57  	}
    58  
    59  	for _, h := range host {
    60  		if ip := net.ParseIP(h); ip != nil {
    61  			template.IPAddresses = append(template.IPAddresses, ip)
    62  		} else {
    63  			template.DNSNames = append(template.DNSNames, h)
    64  		}
    65  	}
    66  
    67  	template.IsCA = true
    68  	template.KeyUsage |= x509.KeyUsageCertSign
    69  
    70  	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
    71  	if err != nil {
    72  		return tls.Certificate{}, err
    73  	}
    74  
    75  	// create public key
    76  	certOut := bytes.NewBuffer(nil)
    77  	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
    78  
    79  	// create private key
    80  	keyOut := bytes.NewBuffer(nil)
    81  	b, err := x509.MarshalECPrivateKey(priv)
    82  	if err != nil {
    83  		return tls.Certificate{}, err
    84  	}
    85  	pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b})
    86  
    87  	return tls.X509KeyPair(certOut.Bytes(), keyOut.Bytes())
    88  }