sigs.k8s.io/cluster-api@v1.7.1/util/certs/certs.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // Package certs implements cert handling utilities. 18 package certs 19 20 import ( 21 "crypto" 22 "crypto/rand" 23 "crypto/rsa" 24 "crypto/x509" 25 "encoding/pem" 26 27 "github.com/pkg/errors" 28 kerrors "k8s.io/apimachinery/pkg/util/errors" 29 ) 30 31 // NewPrivateKey creates an RSA private key. 32 func NewPrivateKey() (*rsa.PrivateKey, error) { 33 pk, err := rsa.GenerateKey(rand.Reader, DefaultRSAKeySize) 34 return pk, errors.WithStack(err) 35 } 36 37 // EncodeCertPEM returns PEM-endcoded certificate data. 38 func EncodeCertPEM(cert *x509.Certificate) []byte { 39 block := pem.Block{ 40 Type: "CERTIFICATE", 41 Bytes: cert.Raw, 42 } 43 return pem.EncodeToMemory(&block) 44 } 45 46 // EncodePrivateKeyPEM returns PEM-encoded private key data. 47 func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte { 48 block := pem.Block{ 49 Type: "RSA PRIVATE KEY", 50 Bytes: x509.MarshalPKCS1PrivateKey(key), 51 } 52 53 return pem.EncodeToMemory(&block) 54 } 55 56 // EncodePublicKeyPEM returns PEM-encoded public key data. 57 func EncodePublicKeyPEM(key *rsa.PublicKey) ([]byte, error) { 58 der, err := x509.MarshalPKIXPublicKey(key) 59 if err != nil { 60 return []byte{}, errors.WithStack(err) 61 } 62 block := pem.Block{ 63 Type: "PUBLIC KEY", 64 Bytes: der, 65 } 66 return pem.EncodeToMemory(&block), nil 67 } 68 69 // DecodeCertPEM attempts to return a decoded certificate or nil 70 // if the encoded input does not contain a certificate. 71 func DecodeCertPEM(encoded []byte) (*x509.Certificate, error) { 72 block, _ := pem.Decode(encoded) 73 if block == nil { 74 return nil, errors.New("unable to decode PEM data") 75 } 76 77 return x509.ParseCertificate(block.Bytes) 78 } 79 80 // DecodePrivateKeyPEM attempts to return a decoded key or nil 81 // if the encoded input does not contain a private key. 82 func DecodePrivateKeyPEM(encoded []byte) (crypto.Signer, error) { 83 block, _ := pem.Decode(encoded) 84 if block == nil { 85 return nil, errors.New("unable to decode PEM data") 86 } 87 88 errs := []error{} 89 pkcs1Key, pkcs1Err := x509.ParsePKCS1PrivateKey(block.Bytes) 90 if pkcs1Err == nil { 91 return crypto.Signer(pkcs1Key), nil 92 } 93 errs = append(errs, pkcs1Err) 94 95 // ParsePKCS1PrivateKey will fail with errors.New for many reasons 96 // including if the format is wrong, so we can retry with PKCS8 or EC 97 // https://golang.org/src/crypto/x509/pkcs1.go#L58 98 pkcs8Key, pkcs8Err := x509.ParsePKCS8PrivateKey(block.Bytes) 99 if pkcs8Err == nil { 100 pkcs8Signer, ok := pkcs8Key.(crypto.Signer) 101 if !ok { 102 return nil, errors.New("x509: certificate private key does not implement crypto.Signer") 103 } 104 return pkcs8Signer, nil 105 } 106 errs = append(errs, pkcs8Err) 107 108 ecKey, ecErr := x509.ParseECPrivateKey(block.Bytes) 109 if ecErr == nil { 110 return crypto.Signer(ecKey), nil 111 } 112 errs = append(errs, ecErr) 113 114 return nil, kerrors.NewAggregate(errs) 115 }