github.com/moqsien/xraycore@v1.8.5/common/protocol/tls/cert/cert.go (about)

     1  package cert
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"crypto/ed25519"
     6  	"crypto/elliptic"
     7  	"crypto/rand"
     8  	"crypto/rsa"
     9  	"crypto/x509"
    10  	"encoding/asn1"
    11  	"encoding/pem"
    12  	"math/big"
    13  	"time"
    14  
    15  	"github.com/moqsien/xraycore/common"
    16  )
    17  
    18  //go:generate go run github.com/moqsien/xraycore/common/errors/errorgen
    19  
    20  type Certificate struct {
    21  	// Cerificate in ASN.1 DER format
    22  	Certificate []byte
    23  	// Private key in ASN.1 DER format
    24  	PrivateKey []byte
    25  }
    26  
    27  func ParseCertificate(certPEM []byte, keyPEM []byte) (*Certificate, error) {
    28  	certBlock, _ := pem.Decode(certPEM)
    29  	if certBlock == nil {
    30  		return nil, newError("failed to decode certificate")
    31  	}
    32  	keyBlock, _ := pem.Decode(keyPEM)
    33  	if keyBlock == nil {
    34  		return nil, newError("failed to decode key")
    35  	}
    36  	return &Certificate{
    37  		Certificate: certBlock.Bytes,
    38  		PrivateKey:  keyBlock.Bytes,
    39  	}, nil
    40  }
    41  
    42  func (c *Certificate) ToPEM() ([]byte, []byte) {
    43  	return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: c.Certificate}),
    44  		pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: c.PrivateKey})
    45  }
    46  
    47  type Option func(*x509.Certificate)
    48  
    49  func Authority(isCA bool) Option {
    50  	return func(cert *x509.Certificate) {
    51  		cert.IsCA = isCA
    52  	}
    53  }
    54  
    55  func NotBefore(t time.Time) Option {
    56  	return func(c *x509.Certificate) {
    57  		c.NotBefore = t
    58  	}
    59  }
    60  
    61  func NotAfter(t time.Time) Option {
    62  	return func(c *x509.Certificate) {
    63  		c.NotAfter = t
    64  	}
    65  }
    66  
    67  func DNSNames(names ...string) Option {
    68  	return func(c *x509.Certificate) {
    69  		c.DNSNames = names
    70  	}
    71  }
    72  
    73  func CommonName(name string) Option {
    74  	return func(c *x509.Certificate) {
    75  		c.Subject.CommonName = name
    76  	}
    77  }
    78  
    79  func KeyUsage(usage x509.KeyUsage) Option {
    80  	return func(c *x509.Certificate) {
    81  		c.KeyUsage = usage
    82  	}
    83  }
    84  
    85  func Organization(org string) Option {
    86  	return func(c *x509.Certificate) {
    87  		c.Subject.Organization = []string{org}
    88  	}
    89  }
    90  
    91  func MustGenerate(parent *Certificate, opts ...Option) *Certificate {
    92  	cert, err := Generate(parent, opts...)
    93  	common.Must(err)
    94  	return cert
    95  }
    96  
    97  func publicKey(priv interface{}) interface{} {
    98  	switch k := priv.(type) {
    99  	case *rsa.PrivateKey:
   100  		return &k.PublicKey
   101  	case *ecdsa.PrivateKey:
   102  		return &k.PublicKey
   103  	case ed25519.PrivateKey:
   104  		return k.Public().(ed25519.PublicKey)
   105  	default:
   106  		return nil
   107  	}
   108  }
   109  
   110  func Generate(parent *Certificate, opts ...Option) (*Certificate, error) {
   111  	var (
   112  		pKey      interface{}
   113  		parentKey interface{}
   114  		err       error
   115  	)
   116  	// higher signing performance than RSA2048
   117  	selfKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   118  	if err != nil {
   119  		return nil, newError("failed to generate self private key").Base(err)
   120  	}
   121  	parentKey = selfKey
   122  	if parent != nil {
   123  		if _, e := asn1.Unmarshal(parent.PrivateKey, &ecPrivateKey{}); e == nil {
   124  			pKey, err = x509.ParseECPrivateKey(parent.PrivateKey)
   125  		} else if _, e := asn1.Unmarshal(parent.PrivateKey, &pkcs8{}); e == nil {
   126  			pKey, err = x509.ParsePKCS8PrivateKey(parent.PrivateKey)
   127  		} else if _, e := asn1.Unmarshal(parent.PrivateKey, &pkcs1PrivateKey{}); e == nil {
   128  			pKey, err = x509.ParsePKCS1PrivateKey(parent.PrivateKey)
   129  		}
   130  		if err != nil {
   131  			return nil, newError("failed to parse parent private key").Base(err)
   132  		}
   133  		parentKey = pKey
   134  	}
   135  
   136  	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
   137  	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
   138  	if err != nil {
   139  		return nil, newError("failed to generate serial number").Base(err)
   140  	}
   141  
   142  	template := &x509.Certificate{
   143  		SerialNumber:          serialNumber,
   144  		NotBefore:             time.Now().Add(time.Hour * -1),
   145  		NotAfter:              time.Now().Add(time.Hour),
   146  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
   147  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
   148  		BasicConstraintsValid: true,
   149  	}
   150  
   151  	for _, opt := range opts {
   152  		opt(template)
   153  	}
   154  
   155  	parentCert := template
   156  	if parent != nil {
   157  		pCert, err := x509.ParseCertificate(parent.Certificate)
   158  		if err != nil {
   159  			return nil, newError("failed to parse parent certificate").Base(err)
   160  		}
   161  		parentCert = pCert
   162  	}
   163  
   164  	derBytes, err := x509.CreateCertificate(rand.Reader, template, parentCert, publicKey(selfKey), parentKey)
   165  	if err != nil {
   166  		return nil, newError("failed to create certificate").Base(err)
   167  	}
   168  
   169  	privateKey, err := x509.MarshalPKCS8PrivateKey(selfKey)
   170  	if err != nil {
   171  		return nil, newError("Unable to marshal private key").Base(err)
   172  	}
   173  
   174  	return &Certificate{
   175  		Certificate: derBytes,
   176  		PrivateKey:  privateKey,
   177  	}, nil
   178  }