github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/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/xtls/xray-core/common" 16 ) 17 18 //go:generate go run github.com/xtls/xray-core/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 }