2 Copyright 2014 The Kubernetes Authors.
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
8 http://www.apache.org/licenses/LICENSE-2.0
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.
29 // ECPrivateKeyBlockType is a possible value for pem.Block.Type.
30 ECPrivateKeyBlockType = "EC PRIVATE KEY"
31 // RSAPrivateKeyBlockType is a possible value for pem.Block.Type.
32 RSAPrivateKeyBlockType = "RSA PRIVATE KEY"
33 // PrivateKeyBlockType is a possible value for pem.Block.Type.
34 PrivateKeyBlockType = "PRIVATE KEY"
35 // PublicKeyBlockType is a possible value for pem.Block.Type.
36 PublicKeyBlockType = "PUBLIC KEY"
37 // CertificateBlockType is a possible value for pem.Block.Type.
38 CertificateBlockType = "CERTIFICATE"
39 // CertificateRequestBlockType is a possible value for pem.Block.Type.
40 CertificateRequestBlockType = "CERTIFICATE REQUEST"
43 // EncodePublicKeyPEM returns PEM-encoded public data
44 func EncodePublicKeyPEM(key *rsa.PublicKey) ([]byte, error) {
45 der, err := x509.MarshalPKIXPublicKey(key)
50 Type: PublicKeyBlockType,
53 return pem.EncodeToMemory(&block), nil
56 // EncodePrivateKeyPEM returns PEM-encoded private key data
57 func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte {
59 Type: RSAPrivateKeyBlockType,
60 Bytes: x509.MarshalPKCS1PrivateKey(key),
62 return pem.EncodeToMemory(&block)
65 // EncodeCertPEM returns PEM-endcoded certificate data
66 func EncodeCertPEM(cert *x509.Certificate) []byte {
68 Type: CertificateBlockType,
71 return pem.EncodeToMemory(&block)
74 // ParsePrivateKeyPEM returns a private key parsed from a PEM block in the supplied data.
75 // Recognizes PEM blocks for "EC PRIVATE KEY", "RSA PRIVATE KEY", or "PRIVATE KEY"
76 func ParsePrivateKeyPEM(keyData []byte) (interface{}, error) {
77 var privateKeyPemBlock *pem.Block
79 privateKeyPemBlock, keyData = pem.Decode(keyData)
80 if privateKeyPemBlock == nil {
84 switch privateKeyPemBlock.Type {
85 case ECPrivateKeyBlockType:
86 // ECDSA Private Key in ASN.1 format
87 if key, err := x509.ParseECPrivateKey(privateKeyPemBlock.Bytes); err == nil {
90 case RSAPrivateKeyBlockType:
91 // RSA Private Key in PKCS#1 format
92 if key, err := x509.ParsePKCS1PrivateKey(privateKeyPemBlock.Bytes); err == nil {
95 case PrivateKeyBlockType:
96 // RSA or ECDSA Private Key in unencrypted PKCS#8 format
97 if key, err := x509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes); err == nil {
102 // tolerate non-key PEM blocks for compatibility with things like "EC PARAMETERS" blocks
103 // originally, only the first PEM block was parsed and expected to be a key block
106 // we read all the PEM blocks and didn't recognize one
107 return nil, fmt.Errorf("data does not contain a valid RSA or ECDSA private key")
110 // ParsePublicKeysPEM is a helper function for reading an array of rsa.PublicKey or ecdsa.PublicKey from a PEM-encoded byte array.
111 // Reads public keys from both public and private key files.
112 func ParsePublicKeysPEM(keyData []byte) ([]interface{}, error) {
114 keys := []interface{}{}
116 // read the next block
117 block, keyData = pem.Decode(keyData)
122 // test block against parsing functions
123 if privateKey, err := parseRSAPrivateKey(block.Bytes); err == nil {
124 keys = append(keys, &privateKey.PublicKey)
127 if publicKey, err := parseRSAPublicKey(block.Bytes); err == nil {
128 keys = append(keys, publicKey)
131 if privateKey, err := parseECPrivateKey(block.Bytes); err == nil {
132 keys = append(keys, &privateKey.PublicKey)
135 if publicKey, err := parseECPublicKey(block.Bytes); err == nil {
136 keys = append(keys, publicKey)
140 // tolerate non-key PEM blocks for backwards compatibility
141 // originally, only the first PEM block was parsed and expected to be a key block
145 return nil, fmt.Errorf("data does not contain any valid RSA or ECDSA public keys")
150 // ParseCertsPEM returns the x509.Certificates contained in the given PEM-encoded byte array
151 // Returns an error if a certificate could not be parsed, or if the data does not contain any certificates
152 func ParseCertsPEM(pemCerts []byte) ([]*x509.Certificate, error) {
154 certs := []*x509.Certificate{}
155 for len(pemCerts) > 0 {
157 block, pemCerts = pem.Decode(pemCerts)
161 // Only use PEM "CERTIFICATE" blocks without extra headers
162 if block.Type != CertificateBlockType || len(block.Headers) != 0 {
166 cert, err := x509.ParseCertificate(block.Bytes)
171 certs = append(certs, cert)
176 return certs, errors.New("data does not contain any valid RSA or ECDSA certificates")
181 // parseRSAPublicKey parses a single RSA public key from the provided data
182 func parseRSAPublicKey(data []byte) (*rsa.PublicKey, error) {
186 var parsedKey interface{}
187 if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil {
188 if cert, err := x509.ParseCertificate(data); err == nil {
189 parsedKey = cert.PublicKey
195 // Test if parsed key is an RSA Public Key
196 var pubKey *rsa.PublicKey
198 if pubKey, ok = parsedKey.(*rsa.PublicKey); !ok {
199 return nil, fmt.Errorf("data doesn't contain valid RSA Public Key")
205 // parseRSAPrivateKey parses a single RSA private key from the provided data
206 func parseRSAPrivateKey(data []byte) (*rsa.PrivateKey, error) {
210 var parsedKey interface{}
211 if parsedKey, err = x509.ParsePKCS1PrivateKey(data); err != nil {
212 if parsedKey, err = x509.ParsePKCS8PrivateKey(data); err != nil {
217 // Test if parsed key is an RSA Private Key
218 var privKey *rsa.PrivateKey
220 if privKey, ok = parsedKey.(*rsa.PrivateKey); !ok {
221 return nil, fmt.Errorf("data doesn't contain valid RSA Private Key")
227 // parseECPublicKey parses a single ECDSA public key from the provided data
228 func parseECPublicKey(data []byte) (*ecdsa.PublicKey, error) {
232 var parsedKey interface{}
233 if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil {
234 if cert, err := x509.ParseCertificate(data); err == nil {
235 parsedKey = cert.PublicKey
241 // Test if parsed key is an ECDSA Public Key
242 var pubKey *ecdsa.PublicKey
244 if pubKey, ok = parsedKey.(*ecdsa.PublicKey); !ok {
245 return nil, fmt.Errorf("data doesn't contain valid ECDSA Public Key")
251 // parseECPrivateKey parses a single ECDSA private key from the provided data
252 func parseECPrivateKey(data []byte) (*ecdsa.PrivateKey, error) {
256 var parsedKey interface{}
257 if parsedKey, err = x509.ParseECPrivateKey(data); err != nil {
261 // Test if parsed key is an ECDSA Private Key
262 var privKey *ecdsa.PrivateKey
264 if privKey, ok = parsedKey.(*ecdsa.PrivateKey); !ok {
265 return nil, fmt.Errorf("data doesn't contain valid ECDSA Private Key")