github.com/Venafi/vcert/v5@v5.10.2/pkg/util/sshKeyGenerator.go (about)

     1  package util
     2  
     3  import (
     4  	"crypto/rand"
     5  	"crypto/rsa"
     6  	"crypto/x509"
     7  	"encoding/pem"
     8  	"fmt"
     9  	"log"
    10  	"strings"
    11  
    12  	"github.com/youmark/pkcs8"
    13  	"golang.org/x/crypto/ssh"
    14  )
    15  
    16  const (
    17  	RsaPrivKeyType = "RSA PRIVATE KEY"
    18  )
    19  
    20  func generatePrivKey(bitSize int) (*rsa.PrivateKey, error) {
    21  
    22  	privKey, err := rsa.GenerateKey(rand.Reader, bitSize)
    23  	if err != nil {
    24  		return nil, err
    25  	}
    26  
    27  	err = privKey.Validate()
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  
    32  	log.Println("Private Key was generated")
    33  	return privKey, nil
    34  }
    35  
    36  func encodePrivKeyToPEM(privateKey *rsa.PrivateKey, keyPassword string, format ...string) ([]byte, error) {
    37  
    38  	var err error
    39  	var privBlock *pem.Block
    40  	var privDER []byte
    41  	if keyPassword != "" {
    42  		if format[0] == LegacyPem {
    43  			privDER := x509.MarshalPKCS1PrivateKey(privateKey)
    44  			privBlock, err = X509EncryptPEMBlock(rand.Reader, RsaPrivKeyType, privDER, []byte(keyPassword), PEMCipherDES)
    45  			if err != nil {
    46  				return nil, err
    47  			}
    48  		} else {
    49  			privDER, err = pkcs8.MarshalPrivateKey(privateKey, []byte(keyPassword), nil)
    50  			if err != nil {
    51  				return nil, err
    52  			}
    53  			privBlock = &pem.Block{
    54  				Type:    "ENCRYPTED PRIVATE KEY",
    55  				Headers: nil,
    56  				Bytes:   privDER,
    57  			}
    58  		}
    59  	} else {
    60  		if format[0] == LegacyPem {
    61  			privDER = x509.MarshalPKCS1PrivateKey(privateKey)
    62  			privBlock = &pem.Block{
    63  				Type:    RsaPrivKeyType,
    64  				Headers: nil,
    65  				Bytes:   privDER,
    66  			}
    67  		} else {
    68  			privDER, err := pkcs8.MarshalPrivateKey(privateKey, nil, nil)
    69  			if err != nil {
    70  				return nil, err
    71  			}
    72  			privBlock = &pem.Block{
    73  				Type:    "PRIVATE KEY",
    74  				Headers: nil,
    75  				Bytes:   privDER,
    76  			}
    77  		}
    78  	}
    79  
    80  	privatePEM := pem.EncodeToMemory(privBlock)
    81  
    82  	return privatePEM, nil
    83  }
    84  
    85  func generatePublicKey(key *rsa.PublicKey) ([]byte, error) {
    86  
    87  	publicRsaKey, err := ssh.NewPublicKey(key)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	pubKeyBytes := ssh.MarshalAuthorizedKey(publicRsaKey)
    93  
    94  	log.Println("Public key was generated")
    95  	return pubKeyBytes, nil
    96  
    97  }
    98  
    99  func GenerateSshKeyPair(bitSize int, keyPassword, certId string, format ...string) ([]byte, []byte, error) {
   100  
   101  	currentFormat := ""
   102  	if len(format) > 0 && format[0] != "" {
   103  		currentFormat = format[0]
   104  	}
   105  
   106  	privateKey, err := generatePrivKey(bitSize)
   107  
   108  	if err != nil {
   109  		return nil, nil, err
   110  	}
   111  
   112  	publicKeyBytes, err := generatePublicKey(&privateKey.PublicKey)
   113  
   114  	if err != nil {
   115  		return nil, nil, err
   116  	}
   117  
   118  	privateKeyBytes, err := encodePrivKeyToPEM(privateKey, keyPassword, currentFormat)
   119  
   120  	if err != nil {
   121  		return nil, nil, err
   122  	}
   123  
   124  	sPubKey := string(publicKeyBytes)
   125  	sPubKey = strings.TrimRight(sPubKey, "\r\n")
   126  	sPubKey = fmt.Sprint(sPubKey, " ", certId)
   127  
   128  	return privateKeyBytes, []byte(sPubKey), nil
   129  
   130  }