github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/utils/ssh/generate.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package ssh
     5  
     6  import (
     7  	"crypto/rand"
     8  	"crypto/rsa"
     9  	"crypto/x509"
    10  	"encoding/pem"
    11  	"fmt"
    12  	"strings"
    13  
    14  	"code.google.com/p/go.crypto/ssh"
    15  	"github.com/juju/errors"
    16  )
    17  
    18  // rsaGenerateKey allows for tests to patch out rsa key generation
    19  var rsaGenerateKey = rsa.GenerateKey
    20  
    21  // KeyBits is used to determine the number of bits to use for the RSA keys
    22  // created using the GenerateKey function.
    23  var KeyBits = 2048
    24  
    25  // GenerateKey makes a 2048 bit RSA no-passphrase SSH capable key.  The bit
    26  // size is actually controlled by the KeyBits var. The private key returned is
    27  // encoded to ASCII using the PKCS1 encoding.  The public key is suitable to
    28  // be added into an authorized_keys file, and has the comment passed in as the
    29  // comment part of the key.
    30  func GenerateKey(comment string) (private, public string, err error) {
    31  	key, err := rsaGenerateKey(rand.Reader, KeyBits)
    32  	if err != nil {
    33  		return "", "", errors.Trace(err)
    34  	}
    35  
    36  	identity := pem.EncodeToMemory(
    37  		&pem.Block{
    38  			Type:  "RSA PRIVATE KEY",
    39  			Bytes: x509.MarshalPKCS1PrivateKey(key),
    40  		})
    41  
    42  	public, err = PublicKey(identity, comment)
    43  	if err != nil {
    44  		return "", "", errors.Trace(err)
    45  	}
    46  
    47  	return string(identity), public, nil
    48  }
    49  
    50  // PublicKey returns the public key for any private key. The public key is
    51  // suitable to be added into an authorized_keys file, and has the comment
    52  // passed in as the comment part of the key.
    53  func PublicKey(privateKey []byte, comment string) (string, error) {
    54  	signer, err := ssh.ParsePrivateKey(privateKey)
    55  	if err != nil {
    56  		return "", errors.Annotate(err, "failed to load key")
    57  	}
    58  
    59  	auth_key := string(ssh.MarshalAuthorizedKey(signer.PublicKey()))
    60  	// Strip off the trailing new line so we can add a comment.
    61  	auth_key = strings.TrimSpace(auth_key)
    62  	public := fmt.Sprintf("%s %s\n", auth_key, comment)
    63  
    64  	return public, nil
    65  }