github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/cloudflare/cfssl/initca/initca.go (about) 1 // Package initca contains code to initialise a certificate authority, 2 // generating a new root key and certificate. 3 package initca 4 5 import ( 6 "crypto" 7 "crypto/rsa" 8 "errors" 9 "github.com/hellobchain/newcryptosm/ecdsa" 10 "github.com/hellobchain/newcryptosm/x509" 11 "time" 12 13 "github.com/hellobchain/third_party/cloudflare/cfssl/config" 14 "github.com/hellobchain/third_party/cloudflare/cfssl/csr" 15 cferr "github.com/hellobchain/third_party/cloudflare/cfssl/errors" 16 "github.com/hellobchain/third_party/cloudflare/cfssl/helpers" 17 "github.com/hellobchain/third_party/cloudflare/cfssl/log" 18 "github.com/hellobchain/third_party/cloudflare/cfssl/signer" 19 "github.com/hellobchain/third_party/cloudflare/cfssl/signer/local" 20 ) 21 22 // validator contains the default validation logic for certificate 23 // authority certificates. The only requirement here is that the 24 // certificate have a non-empty subject field. 25 func validator(req *csr.CertificateRequest) error { 26 if req.CN != "" { 27 return nil 28 } 29 30 if len(req.Names) == 0 { 31 return cferr.Wrap(cferr.PolicyError, cferr.InvalidRequest, errors.New("missing subject information")) 32 } 33 34 for i := range req.Names { 35 if csr.IsNameEmpty(req.Names[i]) { 36 return cferr.Wrap(cferr.PolicyError, cferr.InvalidRequest, errors.New("missing subject information")) 37 } 38 } 39 40 return nil 41 } 42 43 // New creates a new root certificate from the certificate request. 44 func New(defaultAlgo string, req *csr.CertificateRequest) (cert, csrPEM, key []byte, err error) { 45 policy := CAPolicy() 46 if req.CA != nil { 47 if req.CA.Expiry != "" { 48 policy.Default.ExpiryString = req.CA.Expiry 49 policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry) 50 if err != nil { 51 return 52 } 53 } 54 55 policy.Default.CAConstraint.MaxPathLen = req.CA.PathLength 56 if req.CA.PathLength != 0 && req.CA.PathLenZero { 57 log.Infof("ignore invalid 'pathlenzero' value") 58 } else { 59 policy.Default.CAConstraint.MaxPathLenZero = req.CA.PathLenZero 60 } 61 } 62 63 g := &csr.Generator{Validator: validator} 64 csrPEM, key, err = g.ProcessRequest(defaultAlgo, req) 65 if err != nil { 66 log.Errorf("failed to process request: %v", err) 67 key = nil 68 return 69 } 70 71 priv, err := helpers.ParsePrivateKeyPEM(key) 72 if err != nil { 73 log.Errorf("failed to parse private key: %v", err) 74 return 75 } 76 77 s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), policy) 78 if err != nil { 79 log.Errorf("failed to create signer: %v", err) 80 return 81 } 82 83 signReq := signer.SignRequest{Hosts: req.Hosts, Request: string(csrPEM)} 84 cert, err = s.Sign(signReq) 85 86 return 87 88 } 89 90 // NewFromPEM creates a new root certificate from the key file passed in. 91 func NewFromPEM(req *csr.CertificateRequest, keyFile string) (cert, csrPEM []byte, err error) { 92 privData, err := helpers.ReadBytes(keyFile) 93 if err != nil { 94 return nil, nil, err 95 } 96 97 priv, err := helpers.ParsePrivateKeyPEM(privData) 98 if err != nil { 99 return nil, nil, err 100 } 101 102 return NewFromSigner(req, priv) 103 } 104 105 // RenewFromPEM re-creates a root certificate from the CA cert and key 106 // files. The resulting root certificate will have the input CA certificate 107 // as the template and have the same expiry length. E.g. the exsiting CA 108 // is valid for a year from Jan 01 2015 to Jan 01 2016, the renewed certificate 109 // will be valid from now and expire in one year as well. 110 func RenewFromPEM(caFile, keyFile string) ([]byte, error) { 111 caBytes, err := helpers.ReadBytes(caFile) 112 if err != nil { 113 return nil, err 114 } 115 116 ca, err := helpers.ParseCertificatePEM(caBytes) 117 if err != nil { 118 return nil, err 119 } 120 121 keyBytes, err := helpers.ReadBytes(keyFile) 122 if err != nil { 123 return nil, err 124 } 125 126 key, err := helpers.ParsePrivateKeyPEM(keyBytes) 127 if err != nil { 128 return nil, err 129 } 130 131 return RenewFromSigner(ca, key) 132 } 133 134 // NewFromSigner creates a new root certificate from a crypto.Signer. 135 func NewFromSigner(req *csr.CertificateRequest, priv crypto.Signer) (cert, csrPEM []byte, err error) { 136 policy := CAPolicy() 137 if req.CA != nil { 138 if req.CA.Expiry != "" { 139 policy.Default.ExpiryString = req.CA.Expiry 140 policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry) 141 if err != nil { 142 return nil, nil, err 143 } 144 } 145 146 policy.Default.CAConstraint.MaxPathLen = req.CA.PathLength 147 if req.CA.PathLength != 0 && req.CA.PathLenZero == true { 148 log.Infof("ignore invalid 'pathlenzero' value") 149 } else { 150 policy.Default.CAConstraint.MaxPathLenZero = req.CA.PathLenZero 151 } 152 } 153 154 csrPEM, err = csr.Generate(priv, req) 155 if err != nil { 156 return nil, nil, err 157 } 158 159 s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), policy) 160 if err != nil { 161 log.Errorf("failed to create signer: %v", err) 162 return 163 } 164 165 signReq := signer.SignRequest{Request: string(csrPEM)} 166 cert, err = s.Sign(signReq) 167 return 168 } 169 170 // RenewFromSigner re-creates a root certificate from the CA cert and crypto.Signer. 171 // The resulting root certificate will have ca certificate 172 // as the template and have the same expiry length. E.g. the exsiting CA 173 // is valid for a year from Jan 01 2015 to Jan 01 2016, the renewed certificate 174 // will be valid from now and expire in one year as well. 175 func RenewFromSigner(ca *x509.Certificate, priv crypto.Signer) ([]byte, error) { 176 if !ca.IsCA { 177 return nil, errors.New("input certificate is not a CA cert") 178 } 179 var defaultAlgo string 180 // matching certificate public key vs private key 181 switch { 182 case ca.PublicKeyAlgorithm == x509.RSA: 183 184 var rsaPublicKey *rsa.PublicKey 185 var ok bool 186 if rsaPublicKey, ok = priv.Public().(*rsa.PublicKey); !ok { 187 return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch) 188 } 189 if ca.PublicKey.(*rsa.PublicKey).N.Cmp(rsaPublicKey.N) != 0 { 190 return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch) 191 } 192 defaultAlgo = "rsa" 193 case ca.PublicKeyAlgorithm == x509.ECDSA: 194 var ecdsaPublicKey *ecdsa.PublicKey 195 var ok bool 196 if ecdsaPublicKey, ok = priv.Public().(*ecdsa.PublicKey); !ok { 197 return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch) 198 } 199 if ca.PublicKey.(*ecdsa.PublicKey).X.Cmp(ecdsaPublicKey.X) != 0 { 200 return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch) 201 } 202 defaultAlgo = "ecdsa" 203 case ca.PublicKeyAlgorithm == x509.SM2: 204 var ecdsaPublicKey *ecdsa.PublicKey 205 var ok bool 206 if ecdsaPublicKey, ok = priv.Public().(*ecdsa.PublicKey); !ok { 207 return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch) 208 } 209 if ca.PublicKey.(*ecdsa.PublicKey).X.Cmp(ecdsaPublicKey.X) != 0 { 210 return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch) 211 } 212 defaultAlgo = "sm2" 213 default: 214 return nil, cferr.New(cferr.PrivateKeyError, cferr.NotRSAOrECC) 215 } 216 217 req := csr.ExtractCertificateRequest(defaultAlgo, ca) 218 219 cert, _, err := NewFromSigner(req, priv) 220 return cert, err 221 222 } 223 224 // CAPolicy contains the CA issuing policy as default policy. 225 var CAPolicy = func() *config.Signing { 226 return &config.Signing{ 227 Default: &config.SigningProfile{ 228 Usage: []string{"cert sign", "crl sign"}, 229 ExpiryString: "43800h", 230 Expiry: 5 * helpers.OneYear, 231 CAConstraint: config.CAConstraint{IsCA: true}, 232 }, 233 } 234 }