github.com/ztalab/ZACA@v0.0.1/pkg/pkiutil/generate_csr.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Provides utility methods to generate X.509 certificates with different 16 // options. This implementation is Largely inspired from 17 // https://golang.org/src/crypto/tls/generate_cert.go. 18 19 package pkiutil 20 21 import ( 22 "crypto" 23 "crypto/ecdsa" 24 "crypto/elliptic" 25 "crypto/rand" 26 "crypto/rsa" 27 "crypto/x509" 28 "crypto/x509/pkix" 29 "errors" 30 "fmt" 31 "io/ioutil" 32 "os" 33 "strings" 34 ) 35 36 // minimumRsaKeySize is the minimum RSA key size to generate certificates 37 // to ensure proper security 38 const minimumRsaKeySize = 2048 39 40 // GenCSR generates a X.509 certificate sign request and private key with the given options. 41 func GenCSR(options CertOptions) ([]byte, []byte, error) { 42 var priv interface{} 43 var err error 44 if options.ECSigAlg != "" { 45 switch options.ECSigAlg { 46 case EcdsaSigAlg: 47 priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 48 if err != nil { 49 return nil, nil, fmt.Errorf("EC key generation failed (%v)", err) 50 } 51 default: 52 return nil, nil, errors.New("csr cert generation fails due to unsupported EC signature algorithm") 53 } 54 } else { 55 if options.RSAKeySize < minimumRsaKeySize { 56 return nil, nil, fmt.Errorf("requested key size does not meet the minimum requied size of %d (requested: %d)", minimumRsaKeySize, options.RSAKeySize) 57 } 58 59 priv, err = rsa.GenerateKey(rand.Reader, options.RSAKeySize) 60 if err != nil { 61 return nil, nil, fmt.Errorf("RSA key generation failed (%v)", err) 62 } 63 } 64 template, err := GenCSRTemplate(options) 65 if err != nil { 66 return nil, nil, fmt.Errorf("CSR template creation failed (%v)", err) 67 } 68 69 csrBytes, err := x509.CreateCertificateRequest(rand.Reader, template, crypto.PrivateKey(priv)) 70 if err != nil { 71 return nil, nil, fmt.Errorf("CSR creation failed (%v)", err) 72 } 73 74 csr, privKey, err := encodePem(true, csrBytes, priv, options.PKCS8Key) 75 return csr, privKey, err 76 } 77 78 // GenCSRTemplate generates a certificateRequest template with the given options. 79 func GenCSRTemplate(options CertOptions) (*x509.CertificateRequest, error) { 80 template := &x509.CertificateRequest{ 81 Subject: pkix.Name{ 82 Organization: []string{options.Org}, 83 }, 84 } 85 86 if h := options.Host; len(h) > 0 { 87 s, err := BuildSubjectAltNameExtension(h) 88 if err != nil { 89 return nil, err 90 } 91 if options.IsDualUse { 92 cn, err := DualUseCommonName(h) 93 if err != nil { 94 // log and continue 95 fmt.Fprintf(os.Stderr,"dual-use failed for CSR template - omitting CN (%v)", err) 96 } else { 97 template.Subject.CommonName = cn 98 } 99 } 100 template.ExtraExtensions = []pkix.Extension{*s} 101 } 102 103 return template, nil 104 } 105 106 // AppendRootCerts appends root certificates in RootCertFile to the input certificate. 107 func AppendRootCerts(pemCert []byte, rootCertFile string) ([]byte, error) { 108 var rootCerts []byte 109 if len(pemCert) > 0 { 110 // Copy the input certificate 111 rootCerts = make([]byte, len(pemCert)) 112 copy(rootCerts, pemCert) 113 } 114 if len(rootCertFile) > 0 { 115 fmt.Printf("append root certificates from %v", rootCertFile) 116 certBytes, err := ioutil.ReadFile(rootCertFile) 117 if err != nil { 118 return rootCerts, fmt.Errorf("failed to read root certificates (%v)", err) 119 } 120 fmt.Printf("The root certificates to be appended is: %v", rootCertFile) 121 if len(rootCerts) > 0 { 122 // Append a newline after the last cert 123 rootCerts = []byte(strings.TrimSuffix(string(rootCerts), "\n") + "\n") 124 } 125 rootCerts = append(rootCerts, certBytes...) 126 } 127 return rootCerts, nil 128 }