text: package sign
  
  import (
  	"crypto/rsa"
  	"crypto/x509"
  	"encoding/pem"
  	"fmt"
  	"io"
  	"io/ioutil"
  	"os"
  )
  
  // LoadPEMPrivKeyFile reads a PEM encoded RSA private key from the file name.
  // A new RSA private key will be returned if no error.
  func LoadPEMPrivKeyFile(name string) (*rsa.PrivateKey, error) {
  	file, err := os.Open(name)
  	if err != nil {
  		return nil, err
  	}
  	defer file.Close()
  
  	return LoadPEMPrivKey(file)
  }
  
  // LoadPEMPrivKey reads a PEM encoded RSA private key from the io.Reader.
  // A new RSA private key will be returned if no error.
  func LoadPEMPrivKey(reader io.Reader) (*rsa.PrivateKey, error) {
  	block, err := loadPem(reader)
  	if err != nil {
  		return nil, err
  	}
  
  	return x509.ParsePKCS1PrivateKey(block.Bytes)
  }
  
  // LoadEncryptedPEMPrivKey decrypts the PEM encoded private key using the
  // password provided returning a RSA private key. If the PEM data is invalid,
  // or unable to decrypt an error will be returned.
  func LoadEncryptedPEMPrivKey(reader io.Reader, password []byte) (*rsa.PrivateKey, error) {
  	block, err := loadPem(reader)
  	if err != nil {
  		return nil, err
  	}
  
  	decryptedBlock, err := x509.DecryptPEMBlock(block, password)
  	if err != nil {
  		return nil, err
  	}
  
  	return x509.ParsePKCS1PrivateKey(decryptedBlock)
  }
  
  func loadPem(reader io.Reader) (*pem.Block, error) {
  	b, err := ioutil.ReadAll(reader)
  	if err != nil {
  		return nil, err
  	}
  
  	block, _ := pem.Decode(b)
  	if block == nil {
  		// pem.Decode will set block to nil if there is no PEM data in the input
  		// the second parameter will contain the provided bytes that failed
  		// to be decoded.
  		return nil, fmt.Errorf("no valid PEM data provided")
  	}
  
  	return block, nil
  }
  