cert.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package cert
  14. import (
  15. "bytes"
  16. "crypto/ecdsa"
  17. "crypto/elliptic"
  18. cryptorand "crypto/rand"
  19. "crypto/rsa"
  20. "crypto/x509"
  21. "crypto/x509/pkix"
  22. "encoding/pem"
  23. "errors"
  24. "fmt"
  25. "math"
  26. "math/big"
  27. "net"
  28. "time"
  29. )
  30. const (
  31. rsaKeySize = 2048
  32. duration365d = time.Hour * 24 * 365
  33. )
  34. // Config contains the basic fields required for creating a certificate
  35. type Config struct {
  36. CommonName string
  37. Organization []string
  38. AltNames AltNames
  39. Usages []x509.ExtKeyUsage
  40. }
  41. // AltNames contains the domain names and IP addresses that will be added
  42. // to the API Server's x509 certificate SubAltNames field. The values will
  43. // be passed directly to the x509.Certificate object.
  44. type AltNames struct {
  45. DNSNames []string
  46. IPs []net.IP
  47. }
  48. // NewPrivateKey creates an RSA private key
  49. func NewPrivateKey() (*rsa.PrivateKey, error) {
  50. return rsa.GenerateKey(cryptorand.Reader, rsaKeySize)
  51. }
  52. // NewSelfSignedCACert creates a CA certificate
  53. func NewSelfSignedCACert(cfg Config, key *rsa.PrivateKey) (*x509.Certificate, error) {
  54. now := time.Now()
  55. tmpl := x509.Certificate{
  56. SerialNumber: new(big.Int).SetInt64(0),
  57. Subject: pkix.Name{
  58. CommonName: cfg.CommonName,
  59. Organization: cfg.Organization,
  60. },
  61. NotBefore: now.UTC(),
  62. NotAfter: now.Add(duration365d * 10).UTC(),
  63. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
  64. BasicConstraintsValid: true,
  65. IsCA: true,
  66. }
  67. certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &tmpl, &tmpl, key.Public(), key)
  68. if err != nil {
  69. return nil, err
  70. }
  71. return x509.ParseCertificate(certDERBytes)
  72. }
  73. // NewSignedCert creates a signed certificate using the given CA certificate and key
  74. func NewSignedCert(cfg Config, key *rsa.PrivateKey, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, error) {
  75. serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64))
  76. if err != nil {
  77. return nil, err
  78. }
  79. if len(cfg.CommonName) == 0 {
  80. return nil, errors.New("must specify a CommonName")
  81. }
  82. if len(cfg.Usages) == 0 {
  83. return nil, errors.New("must specify at least one ExtKeyUsage")
  84. }
  85. certTmpl := x509.Certificate{
  86. Subject: pkix.Name{
  87. CommonName: cfg.CommonName,
  88. Organization: cfg.Organization,
  89. },
  90. DNSNames: cfg.AltNames.DNSNames,
  91. IPAddresses: cfg.AltNames.IPs,
  92. SerialNumber: serial,
  93. NotBefore: caCert.NotBefore,
  94. NotAfter: time.Now().Add(duration365d).UTC(),
  95. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  96. ExtKeyUsage: cfg.Usages,
  97. }
  98. certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &certTmpl, caCert, key.Public(), caKey)
  99. if err != nil {
  100. return nil, err
  101. }
  102. return x509.ParseCertificate(certDERBytes)
  103. }
  104. // MakeEllipticPrivateKeyPEM creates an ECDSA private key
  105. func MakeEllipticPrivateKeyPEM() ([]byte, error) {
  106. privateKey, err := ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader)
  107. if err != nil {
  108. return nil, err
  109. }
  110. derBytes, err := x509.MarshalECPrivateKey(privateKey)
  111. if err != nil {
  112. return nil, err
  113. }
  114. privateKeyPemBlock := &pem.Block{
  115. Type: ECPrivateKeyBlockType,
  116. Bytes: derBytes,
  117. }
  118. return pem.EncodeToMemory(privateKeyPemBlock), nil
  119. }
  120. // GenerateSelfSignedCertKey creates a self-signed certificate and key for the given host.
  121. // Host may be an IP or a DNS name
  122. // You may also specify additional subject alt names (either ip or dns names) for the certificate
  123. func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS []string) ([]byte, []byte, error) {
  124. caKey, err := rsa.GenerateKey(cryptorand.Reader, 2048)
  125. if err != nil {
  126. return nil, nil, err
  127. }
  128. caTemplate := x509.Certificate{
  129. SerialNumber: big.NewInt(1),
  130. Subject: pkix.Name{
  131. CommonName: fmt.Sprintf("%s-ca@%d", host, time.Now().Unix()),
  132. },
  133. NotBefore: time.Now(),
  134. NotAfter: time.Now().Add(time.Hour * 24 * 365),
  135. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
  136. BasicConstraintsValid: true,
  137. IsCA: true,
  138. }
  139. caDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &caTemplate, &caTemplate, &caKey.PublicKey, caKey)
  140. if err != nil {
  141. return nil, nil, err
  142. }
  143. caCertificate, err := x509.ParseCertificate(caDERBytes)
  144. if err != nil {
  145. return nil, nil, err
  146. }
  147. priv, err := rsa.GenerateKey(cryptorand.Reader, 2048)
  148. if err != nil {
  149. return nil, nil, err
  150. }
  151. template := x509.Certificate{
  152. SerialNumber: big.NewInt(2),
  153. Subject: pkix.Name{
  154. CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()),
  155. },
  156. NotBefore: time.Now(),
  157. NotAfter: time.Now().Add(time.Hour * 24 * 365),
  158. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  159. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  160. BasicConstraintsValid: true,
  161. }
  162. if ip := net.ParseIP(host); ip != nil {
  163. template.IPAddresses = append(template.IPAddresses, ip)
  164. } else {
  165. template.DNSNames = append(template.DNSNames, host)
  166. }
  167. template.IPAddresses = append(template.IPAddresses, alternateIPs...)
  168. template.DNSNames = append(template.DNSNames, alternateDNS...)
  169. derBytes, err := x509.CreateCertificate(cryptorand.Reader, &template, caCertificate, &priv.PublicKey, caKey)
  170. if err != nil {
  171. return nil, nil, err
  172. }
  173. // Generate cert, followed by ca
  174. certBuffer := bytes.Buffer{}
  175. if err := pem.Encode(&certBuffer, &pem.Block{Type: CertificateBlockType, Bytes: derBytes}); err != nil {
  176. return nil, nil, err
  177. }
  178. if err := pem.Encode(&certBuffer, &pem.Block{Type: CertificateBlockType, Bytes: caDERBytes}); err != nil {
  179. return nil, nil, err
  180. }
  181. // Generate key
  182. keyBuffer := bytes.Buffer{}
  183. if err := pem.Encode(&keyBuffer, &pem.Block{Type: RSAPrivateKeyBlockType, Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
  184. return nil, nil, err
  185. }
  186. return certBuffer.Bytes(), keyBuffer.Bytes(), nil
  187. }
  188. // FormatBytesCert receives byte array certificate and formats in human-readable format
  189. func FormatBytesCert(cert []byte) (string, error) {
  190. block, _ := pem.Decode(cert)
  191. c, err := x509.ParseCertificate(block.Bytes)
  192. if err != nil {
  193. return "", fmt.Errorf("failed to parse certificate [%v]", err)
  194. }
  195. return FormatCert(c), nil
  196. }
  197. // FormatCert receives certificate and formats in human-readable format
  198. func FormatCert(c *x509.Certificate) string {
  199. var ips []string
  200. for _, ip := range c.IPAddresses {
  201. ips = append(ips, ip.String())
  202. }
  203. altNames := append(ips, c.DNSNames...)
  204. res := fmt.Sprintf(
  205. "Issuer: CN=%s | Subject: CN=%s | CA: %t\n",
  206. c.Issuer.CommonName, c.Subject.CommonName, c.IsCA,
  207. )
  208. res += fmt.Sprintf("Not before: %s Not After: %s", c.NotBefore, c.NotAfter)
  209. if len(altNames) > 0 {
  210. res += fmt.Sprintf("\nAlternate Names: %v", altNames)
  211. }
  212. return res
  213. }