浏览代码

more options for generating certificate

Darien Raymond 7 年之前
父节点
当前提交
8ba8ce7d6a
共有 1 个文件被更改,包括 44 次插入17 次删除
  1. 44 17
      common/protocol/tls/cert/cert.go

+ 44 - 17
common/protocol/tls/cert/cert.go

@@ -4,13 +4,9 @@ import (
 	"crypto/rand"
 	"crypto/rsa"
 	"crypto/x509"
-	"crypto/x509/pkix"
 	"encoding/pem"
-	"log"
 	"math/big"
 	"time"
-
-	"v2ray.com/core/common"
 )
 
 //go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg cert -path Protocol,TLS,Cert
@@ -30,37 +26,68 @@ func Authority(isCA bool) Option {
 	}
 }
 
-func Generate() (Certificate, error) {
+func NotBefore(t time.Time) Option {
+	return func(c *x509.Certificate) {
+		c.NotBefore = t
+	}
+}
+
+func NotAfter(t time.Time) Option {
+	return func(c *x509.Certificate) {
+		c.NotAfter = t
+	}
+}
+
+func DNSNames(names ...string) Option {
+	return func(c *x509.Certificate) {
+		c.DNSNames = names
+	}
+}
+
+func CommonName(name string) Option {
+	return func(c *x509.Certificate) {
+		c.Subject.CommonName = name
+	}
+}
+
+func Generate(parent *x509.Certificate, opts ...Option) (*Certificate, error) {
 	priv, err := rsa.GenerateKey(rand.Reader, 2048)
-	common.Must(err)
+	if err != nil {
+		return nil, newError("failed to generate RSA private key").Base(err)
+	}
 
 	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
 	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
 	if err != nil {
-
-		log.Fatalf("failed to generate serial number: %s", err)
+		return nil, newError("failed to generate serial number").Base(err)
 	}
 
-	template := x509.Certificate{
-		SerialNumber: serialNumber,
-		Subject: pkix.Name{
-			Organization: []string{"V2Ray Inc"},
-		},
+	template := &x509.Certificate{
+		SerialNumber:          serialNumber,
 		NotBefore:             time.Now().Add(time.Hour * -1),
 		NotAfter:              time.Now().Add(time.Hour),
 		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
 		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
 		BasicConstraintsValid: true,
-		DNSNames:              []string{"www.v2ray.com", "v2ray.com"},
 	}
 
-	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
-	common.Must(err)
+	for _, opt := range opts {
+		opt(template)
+	}
+
+	if parent == nil {
+		parent = template
+	}
+
+	derBytes, err := x509.CreateCertificate(rand.Reader, template, parent, priv.Public(), priv)
+	if err != nil {
+		return nil, newError("failed to create certificate").Base(err)
+	}
 
 	certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
 	keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
 
-	return Certificate{
+	return &Certificate{
 		Certificate: certPEM,
 		PrivateKey:  keyPEM,
 	}, nil