79 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			79 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package tls
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"crypto/ecdsa"
 | |
| 	"crypto/elliptic"
 | |
| 	"crypto/rand"
 | |
| 	"crypto/tls"
 | |
| 	"crypto/x509"
 | |
| 	"crypto/x509/pkix"
 | |
| 	"encoding/pem"
 | |
| 	"math/big"
 | |
| 	"net"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| func Certificate(host ...string) (tls.Certificate, error) {
 | |
| 	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
 | |
| 	if err != nil {
 | |
| 		return tls.Certificate{}, err
 | |
| 	}
 | |
| 
 | |
| 	notBefore := time.Now()
 | |
| 	notAfter := notBefore.Add(time.Hour * 24 * 365)
 | |
| 
 | |
| 	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
 | |
| 	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
 | |
| 	if err != nil {
 | |
| 		return tls.Certificate{}, err
 | |
| 	}
 | |
| 
 | |
| 	template := x509.Certificate{
 | |
| 		SerialNumber: serialNumber,
 | |
| 		Subject: pkix.Name{
 | |
| 			Organization: []string{"Acme Co"},
 | |
| 		},
 | |
| 		NotBefore: notBefore,
 | |
| 		NotAfter:  notAfter,
 | |
| 
 | |
| 		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
 | |
| 		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
 | |
| 		BasicConstraintsValid: true,
 | |
| 	}
 | |
| 
 | |
| 	for _, h := range host {
 | |
| 		if ip := net.ParseIP(h); ip != nil {
 | |
| 			template.IPAddresses = append(template.IPAddresses, ip)
 | |
| 		} else {
 | |
| 			template.DNSNames = append(template.DNSNames, h)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	template.IsCA = true
 | |
| 	template.KeyUsage |= x509.KeyUsageCertSign
 | |
| 
 | |
| 	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
 | |
| 	if err != nil {
 | |
| 		return tls.Certificate{}, err
 | |
| 	}
 | |
| 
 | |
| 	// create public key
 | |
| 	certOut := bytes.NewBuffer(nil)
 | |
| 	if err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
 | |
| 		return tls.Certificate{}, err
 | |
| 	}
 | |
| 
 | |
| 	// create private key
 | |
| 	keyOut := bytes.NewBuffer(nil)
 | |
| 	b, err := x509.MarshalECPrivateKey(priv)
 | |
| 	if err != nil {
 | |
| 		return tls.Certificate{}, err
 | |
| 	}
 | |
| 	if err = pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}); err != nil {
 | |
| 		return tls.Certificate{}, err
 | |
| 	}
 | |
| 
 | |
| 	return tls.X509KeyPair(certOut.Bytes(), keyOut.Bytes())
 | |
| }
 |