github.com/letsencrypt/trillian@v1.1.2-0.20180615153820-ae375a99d36a/crypto/keys/pem/pem.go (about) 1 // Copyright 2017 Google Inc. All Rights Reserved. 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 package pem 16 17 import ( 18 "crypto" 19 "crypto/x509" 20 "encoding/pem" 21 "errors" 22 "fmt" 23 "io/ioutil" 24 25 "github.com/google/trillian/crypto/keys/der" 26 "github.com/google/trillian/crypto/keyspb" 27 ) 28 29 // FromProto takes a PEMKeyFile protobuf message and loads the private key it specifies. 30 func FromProto(pb *keyspb.PEMKeyFile) (crypto.Signer, error) { 31 return ReadPrivateKeyFile(pb.GetPath(), pb.GetPassword()) 32 } 33 34 // ReadPrivateKeyFile reads a PEM-encoded private key from a file. 35 // The key must be protected by a password. 36 func ReadPrivateKeyFile(file, password string) (crypto.Signer, error) { 37 if password == "" { 38 return nil, fmt.Errorf("pemfile: empty password for file %q", file) 39 } 40 41 keyPEM, err := ioutil.ReadFile(file) 42 if err != nil { 43 return nil, fmt.Errorf("pemfile: error reading file %q: %v", file, err) 44 } 45 46 k, err := UnmarshalPrivateKey(string(keyPEM), password) 47 if err != nil { 48 return nil, fmt.Errorf("pemfile: error decoding private key from file %q: %v", file, err) 49 } 50 51 return k, nil 52 } 53 54 // ReadPublicKeyFile reads a PEM-encoded public key from a file. 55 func ReadPublicKeyFile(file string) (crypto.PublicKey, error) { 56 keyPEM, err := ioutil.ReadFile(file) 57 if err != nil { 58 return nil, fmt.Errorf("pemfile: error reading %q: %v", file, err) 59 } 60 61 return UnmarshalPublicKey(string(keyPEM)) 62 } 63 64 // UnmarshalPrivateKey reads a PEM-encoded private key from a string. 65 // The key may be protected by a password. 66 func UnmarshalPrivateKey(keyPEM, password string) (crypto.Signer, error) { 67 block, rest := pem.Decode([]byte(keyPEM)) 68 if block == nil { 69 return nil, errors.New("pemfile: invalid private key PEM") 70 } 71 if len(rest) > 0 { 72 return nil, errors.New("pemfile: extra data found after first PEM block") 73 } 74 75 keyDER := block.Bytes 76 if password != "" { 77 pwdDer, err := x509.DecryptPEMBlock(block, []byte(password)) 78 if err != nil { 79 return nil, fmt.Errorf("pemfile: failed to decrypt: %v", err) 80 } 81 keyDER = pwdDer 82 } 83 84 return der.UnmarshalPrivateKey(keyDER) 85 } 86 87 // UnmarshalPublicKey reads a PEM-encoded public key from a string. 88 func UnmarshalPublicKey(keyPEM string) (crypto.PublicKey, error) { 89 block, rest := pem.Decode([]byte(keyPEM)) 90 if block == nil { 91 return nil, errors.New("pemfile: invalid public key PEM") 92 } 93 if len(rest) > 0 { 94 return nil, errors.New("pemfile: extra data found after first PEM block") 95 } 96 97 return der.UnmarshalPublicKey(block.Bytes) 98 }