github.com/deis/deis@v1.13.5-0.20170519182049-1d9e59fbdbfc/Godeps/_workspace/src/golang.org/x/crypto/ssh/keys.go (about)

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ssh
     6  
     7  import (
     8  	"bytes"
     9  	"crypto"
    10  	"crypto/dsa"
    11  	"crypto/ecdsa"
    12  	"crypto/elliptic"
    13  	"crypto/rsa"
    14  	"crypto/x509"
    15  	"encoding/asn1"
    16  	"encoding/base64"
    17  	"encoding/pem"
    18  	"errors"
    19  	"fmt"
    20  	"io"
    21  	"math/big"
    22  )
    23  
    24  // These constants represent the algorithm names for key types supported by this
    25  // package.
    26  const (
    27  	KeyAlgoRSA      = "ssh-rsa"
    28  	KeyAlgoDSA      = "ssh-dss"
    29  	KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
    30  	KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
    31  	KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
    32  )
    33  
    34  // parsePubKey parses a public key of the given algorithm.
    35  // Use ParsePublicKey for keys with prepended algorithm.
    36  func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) {
    37  	switch algo {
    38  	case KeyAlgoRSA:
    39  		return parseRSA(in)
    40  	case KeyAlgoDSA:
    41  		return parseDSA(in)
    42  	case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
    43  		return parseECDSA(in)
    44  	case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
    45  		cert, err := parseCert(in, certToPrivAlgo(algo))
    46  		if err != nil {
    47  			return nil, nil, err
    48  		}
    49  		return cert, nil, nil
    50  	}
    51  	return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", err)
    52  }
    53  
    54  // parseAuthorizedKey parses a public key in OpenSSH authorized_keys format
    55  // (see sshd(8) manual page) once the options and key type fields have been
    56  // removed.
    57  func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) {
    58  	in = bytes.TrimSpace(in)
    59  
    60  	i := bytes.IndexAny(in, " \t")
    61  	if i == -1 {
    62  		i = len(in)
    63  	}
    64  	base64Key := in[:i]
    65  
    66  	key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key)))
    67  	n, err := base64.StdEncoding.Decode(key, base64Key)
    68  	if err != nil {
    69  		return nil, "", err
    70  	}
    71  	key = key[:n]
    72  	out, err = ParsePublicKey(key)
    73  	if err != nil {
    74  		return nil, "", err
    75  	}
    76  	comment = string(bytes.TrimSpace(in[i:]))
    77  	return out, comment, nil
    78  }
    79  
    80  // ParseAuthorizedKeys parses a public key from an authorized_keys
    81  // file used in OpenSSH according to the sshd(8) manual page.
    82  func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
    83  	for len(in) > 0 {
    84  		end := bytes.IndexByte(in, '\n')
    85  		if end != -1 {
    86  			rest = in[end+1:]
    87  			in = in[:end]
    88  		} else {
    89  			rest = nil
    90  		}
    91  
    92  		end = bytes.IndexByte(in, '\r')
    93  		if end != -1 {
    94  			in = in[:end]
    95  		}
    96  
    97  		in = bytes.TrimSpace(in)
    98  		if len(in) == 0 || in[0] == '#' {
    99  			in = rest
   100  			continue
   101  		}
   102  
   103  		i := bytes.IndexAny(in, " \t")
   104  		if i == -1 {
   105  			in = rest
   106  			continue
   107  		}
   108  
   109  		if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
   110  			return out, comment, options, rest, nil
   111  		}
   112  
   113  		// No key type recognised. Maybe there's an options field at
   114  		// the beginning.
   115  		var b byte
   116  		inQuote := false
   117  		var candidateOptions []string
   118  		optionStart := 0
   119  		for i, b = range in {
   120  			isEnd := !inQuote && (b == ' ' || b == '\t')
   121  			if (b == ',' && !inQuote) || isEnd {
   122  				if i-optionStart > 0 {
   123  					candidateOptions = append(candidateOptions, string(in[optionStart:i]))
   124  				}
   125  				optionStart = i + 1
   126  			}
   127  			if isEnd {
   128  				break
   129  			}
   130  			if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) {
   131  				inQuote = !inQuote
   132  			}
   133  		}
   134  		for i < len(in) && (in[i] == ' ' || in[i] == '\t') {
   135  			i++
   136  		}
   137  		if i == len(in) {
   138  			// Invalid line: unmatched quote
   139  			in = rest
   140  			continue
   141  		}
   142  
   143  		in = in[i:]
   144  		i = bytes.IndexAny(in, " \t")
   145  		if i == -1 {
   146  			in = rest
   147  			continue
   148  		}
   149  
   150  		if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
   151  			options = candidateOptions
   152  			return out, comment, options, rest, nil
   153  		}
   154  
   155  		in = rest
   156  		continue
   157  	}
   158  
   159  	return nil, "", nil, nil, errors.New("ssh: no key found")
   160  }
   161  
   162  // ParsePublicKey parses an SSH public key formatted for use in
   163  // the SSH wire protocol according to RFC 4253, section 6.6.
   164  func ParsePublicKey(in []byte) (out PublicKey, err error) {
   165  	algo, in, ok := parseString(in)
   166  	if !ok {
   167  		return nil, errShortRead
   168  	}
   169  	var rest []byte
   170  	out, rest, err = parsePubKey(in, string(algo))
   171  	if len(rest) > 0 {
   172  		return nil, errors.New("ssh: trailing junk in public key")
   173  	}
   174  
   175  	return out, err
   176  }
   177  
   178  // MarshalAuthorizedKey serializes key for inclusion in an OpenSSH
   179  // authorized_keys file. The return value ends with newline.
   180  func MarshalAuthorizedKey(key PublicKey) []byte {
   181  	b := &bytes.Buffer{}
   182  	b.WriteString(key.Type())
   183  	b.WriteByte(' ')
   184  	e := base64.NewEncoder(base64.StdEncoding, b)
   185  	e.Write(key.Marshal())
   186  	e.Close()
   187  	b.WriteByte('\n')
   188  	return b.Bytes()
   189  }
   190  
   191  // PublicKey is an abstraction of different types of public keys.
   192  type PublicKey interface {
   193  	// Type returns the key's type, e.g. "ssh-rsa".
   194  	Type() string
   195  
   196  	// Marshal returns the serialized key data in SSH wire format,
   197  	// with the name prefix.
   198  	Marshal() []byte
   199  
   200  	// Verify that sig is a signature on the given data using this
   201  	// key. This function will hash the data appropriately first.
   202  	Verify(data []byte, sig *Signature) error
   203  }
   204  
   205  // A Signer can create signatures that verify against a public key.
   206  type Signer interface {
   207  	// PublicKey returns an associated PublicKey instance.
   208  	PublicKey() PublicKey
   209  
   210  	// Sign returns raw signature for the given data. This method
   211  	// will apply the hash specified for the keytype to the data.
   212  	Sign(rand io.Reader, data []byte) (*Signature, error)
   213  }
   214  
   215  type rsaPublicKey rsa.PublicKey
   216  
   217  func (r *rsaPublicKey) Type() string {
   218  	return "ssh-rsa"
   219  }
   220  
   221  // parseRSA parses an RSA key according to RFC 4253, section 6.6.
   222  func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
   223  	var w struct {
   224  		E    *big.Int
   225  		N    *big.Int
   226  		Rest []byte `ssh:"rest"`
   227  	}
   228  	if err := Unmarshal(in, &w); err != nil {
   229  		return nil, nil, err
   230  	}
   231  
   232  	if w.E.BitLen() > 24 {
   233  		return nil, nil, errors.New("ssh: exponent too large")
   234  	}
   235  	e := w.E.Int64()
   236  	if e < 3 || e&1 == 0 {
   237  		return nil, nil, errors.New("ssh: incorrect exponent")
   238  	}
   239  
   240  	var key rsa.PublicKey
   241  	key.E = int(e)
   242  	key.N = w.N
   243  	return (*rsaPublicKey)(&key), w.Rest, nil
   244  }
   245  
   246  func (r *rsaPublicKey) Marshal() []byte {
   247  	e := new(big.Int).SetInt64(int64(r.E))
   248  	wirekey := struct {
   249  		Name string
   250  		E    *big.Int
   251  		N    *big.Int
   252  	}{
   253  		KeyAlgoRSA,
   254  		e,
   255  		r.N,
   256  	}
   257  	return Marshal(&wirekey)
   258  }
   259  
   260  func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
   261  	if sig.Format != r.Type() {
   262  		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
   263  	}
   264  	h := crypto.SHA1.New()
   265  	h.Write(data)
   266  	digest := h.Sum(nil)
   267  	return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig.Blob)
   268  }
   269  
   270  type rsaPrivateKey struct {
   271  	*rsa.PrivateKey
   272  }
   273  
   274  func (r *rsaPrivateKey) PublicKey() PublicKey {
   275  	return (*rsaPublicKey)(&r.PrivateKey.PublicKey)
   276  }
   277  
   278  func (r *rsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
   279  	h := crypto.SHA1.New()
   280  	h.Write(data)
   281  	digest := h.Sum(nil)
   282  	blob, err := rsa.SignPKCS1v15(rand, r.PrivateKey, crypto.SHA1, digest)
   283  	if err != nil {
   284  		return nil, err
   285  	}
   286  	return &Signature{
   287  		Format: r.PublicKey().Type(),
   288  		Blob:   blob,
   289  	}, nil
   290  }
   291  
   292  type dsaPublicKey dsa.PublicKey
   293  
   294  func (r *dsaPublicKey) Type() string {
   295  	return "ssh-dss"
   296  }
   297  
   298  // parseDSA parses an DSA key according to RFC 4253, section 6.6.
   299  func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
   300  	var w struct {
   301  		P, Q, G, Y *big.Int
   302  		Rest       []byte `ssh:"rest"`
   303  	}
   304  	if err := Unmarshal(in, &w); err != nil {
   305  		return nil, nil, err
   306  	}
   307  
   308  	key := &dsaPublicKey{
   309  		Parameters: dsa.Parameters{
   310  			P: w.P,
   311  			Q: w.Q,
   312  			G: w.G,
   313  		},
   314  		Y: w.Y,
   315  	}
   316  	return key, w.Rest, nil
   317  }
   318  
   319  func (k *dsaPublicKey) Marshal() []byte {
   320  	w := struct {
   321  		Name       string
   322  		P, Q, G, Y *big.Int
   323  	}{
   324  		k.Type(),
   325  		k.P,
   326  		k.Q,
   327  		k.G,
   328  		k.Y,
   329  	}
   330  
   331  	return Marshal(&w)
   332  }
   333  
   334  func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
   335  	if sig.Format != k.Type() {
   336  		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
   337  	}
   338  	h := crypto.SHA1.New()
   339  	h.Write(data)
   340  	digest := h.Sum(nil)
   341  
   342  	// Per RFC 4253, section 6.6,
   343  	// The value for 'dss_signature_blob' is encoded as a string containing
   344  	// r, followed by s (which are 160-bit integers, without lengths or
   345  	// padding, unsigned, and in network byte order).
   346  	// For DSS purposes, sig.Blob should be exactly 40 bytes in length.
   347  	if len(sig.Blob) != 40 {
   348  		return errors.New("ssh: DSA signature parse error")
   349  	}
   350  	r := new(big.Int).SetBytes(sig.Blob[:20])
   351  	s := new(big.Int).SetBytes(sig.Blob[20:])
   352  	if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) {
   353  		return nil
   354  	}
   355  	return errors.New("ssh: signature did not verify")
   356  }
   357  
   358  type dsaPrivateKey struct {
   359  	*dsa.PrivateKey
   360  }
   361  
   362  func (k *dsaPrivateKey) PublicKey() PublicKey {
   363  	return (*dsaPublicKey)(&k.PrivateKey.PublicKey)
   364  }
   365  
   366  func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
   367  	h := crypto.SHA1.New()
   368  	h.Write(data)
   369  	digest := h.Sum(nil)
   370  	r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
   371  	if err != nil {
   372  		return nil, err
   373  	}
   374  
   375  	sig := make([]byte, 40)
   376  	rb := r.Bytes()
   377  	sb := s.Bytes()
   378  
   379  	copy(sig[20-len(rb):20], rb)
   380  	copy(sig[40-len(sb):], sb)
   381  
   382  	return &Signature{
   383  		Format: k.PublicKey().Type(),
   384  		Blob:   sig,
   385  	}, nil
   386  }
   387  
   388  type ecdsaPublicKey ecdsa.PublicKey
   389  
   390  func (key *ecdsaPublicKey) Type() string {
   391  	return "ecdsa-sha2-" + key.nistID()
   392  }
   393  
   394  func (key *ecdsaPublicKey) nistID() string {
   395  	switch key.Params().BitSize {
   396  	case 256:
   397  		return "nistp256"
   398  	case 384:
   399  		return "nistp384"
   400  	case 521:
   401  		return "nistp521"
   402  	}
   403  	panic("ssh: unsupported ecdsa key size")
   404  }
   405  
   406  func supportedEllipticCurve(curve elliptic.Curve) bool {
   407  	return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
   408  }
   409  
   410  // ecHash returns the hash to match the given elliptic curve, see RFC
   411  // 5656, section 6.2.1
   412  func ecHash(curve elliptic.Curve) crypto.Hash {
   413  	bitSize := curve.Params().BitSize
   414  	switch {
   415  	case bitSize <= 256:
   416  		return crypto.SHA256
   417  	case bitSize <= 384:
   418  		return crypto.SHA384
   419  	}
   420  	return crypto.SHA512
   421  }
   422  
   423  // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
   424  func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
   425  	identifier, in, ok := parseString(in)
   426  	if !ok {
   427  		return nil, nil, errShortRead
   428  	}
   429  
   430  	key := new(ecdsa.PublicKey)
   431  
   432  	switch string(identifier) {
   433  	case "nistp256":
   434  		key.Curve = elliptic.P256()
   435  	case "nistp384":
   436  		key.Curve = elliptic.P384()
   437  	case "nistp521":
   438  		key.Curve = elliptic.P521()
   439  	default:
   440  		return nil, nil, errors.New("ssh: unsupported curve")
   441  	}
   442  
   443  	var keyBytes []byte
   444  	if keyBytes, in, ok = parseString(in); !ok {
   445  		return nil, nil, errShortRead
   446  	}
   447  
   448  	key.X, key.Y = elliptic.Unmarshal(key.Curve, keyBytes)
   449  	if key.X == nil || key.Y == nil {
   450  		return nil, nil, errors.New("ssh: invalid curve point")
   451  	}
   452  	return (*ecdsaPublicKey)(key), in, nil
   453  }
   454  
   455  func (key *ecdsaPublicKey) Marshal() []byte {
   456  	// See RFC 5656, section 3.1.
   457  	keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y)
   458  	w := struct {
   459  		Name string
   460  		ID   string
   461  		Key  []byte
   462  	}{
   463  		key.Type(),
   464  		key.nistID(),
   465  		keyBytes,
   466  	}
   467  
   468  	return Marshal(&w)
   469  }
   470  
   471  func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
   472  	if sig.Format != key.Type() {
   473  		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
   474  	}
   475  
   476  	h := ecHash(key.Curve).New()
   477  	h.Write(data)
   478  	digest := h.Sum(nil)
   479  
   480  	// Per RFC 5656, section 3.1.2,
   481  	// The ecdsa_signature_blob value has the following specific encoding:
   482  	//    mpint    r
   483  	//    mpint    s
   484  	var ecSig struct {
   485  		R *big.Int
   486  		S *big.Int
   487  	}
   488  
   489  	if err := Unmarshal(sig.Blob, &ecSig); err != nil {
   490  		return err
   491  	}
   492  
   493  	if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) {
   494  		return nil
   495  	}
   496  	return errors.New("ssh: signature did not verify")
   497  }
   498  
   499  type ecdsaPrivateKey struct {
   500  	*ecdsa.PrivateKey
   501  }
   502  
   503  func (k *ecdsaPrivateKey) PublicKey() PublicKey {
   504  	return (*ecdsaPublicKey)(&k.PrivateKey.PublicKey)
   505  }
   506  
   507  func (k *ecdsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
   508  	h := ecHash(k.PrivateKey.PublicKey.Curve).New()
   509  	h.Write(data)
   510  	digest := h.Sum(nil)
   511  	r, s, err := ecdsa.Sign(rand, k.PrivateKey, digest)
   512  	if err != nil {
   513  		return nil, err
   514  	}
   515  
   516  	sig := make([]byte, intLength(r)+intLength(s))
   517  	rest := marshalInt(sig, r)
   518  	marshalInt(rest, s)
   519  	return &Signature{
   520  		Format: k.PublicKey().Type(),
   521  		Blob:   sig,
   522  	}, nil
   523  }
   524  
   525  // NewSignerFromKey takes a pointer to rsa, dsa or ecdsa PrivateKey
   526  // returns a corresponding Signer instance. EC keys should use P256,
   527  // P384 or P521.
   528  func NewSignerFromKey(k interface{}) (Signer, error) {
   529  	var sshKey Signer
   530  	switch t := k.(type) {
   531  	case *rsa.PrivateKey:
   532  		sshKey = &rsaPrivateKey{t}
   533  	case *dsa.PrivateKey:
   534  		sshKey = &dsaPrivateKey{t}
   535  	case *ecdsa.PrivateKey:
   536  		if !supportedEllipticCurve(t.Curve) {
   537  			return nil, errors.New("ssh: only P256, P384 and P521 EC keys are supported.")
   538  		}
   539  
   540  		sshKey = &ecdsaPrivateKey{t}
   541  	default:
   542  		return nil, fmt.Errorf("ssh: unsupported key type %T", k)
   543  	}
   544  	return sshKey, nil
   545  }
   546  
   547  // NewPublicKey takes a pointer to rsa, dsa or ecdsa PublicKey
   548  // and returns a corresponding ssh PublicKey instance. EC keys should use P256, P384 or P521.
   549  func NewPublicKey(k interface{}) (PublicKey, error) {
   550  	var sshKey PublicKey
   551  	switch t := k.(type) {
   552  	case *rsa.PublicKey:
   553  		sshKey = (*rsaPublicKey)(t)
   554  	case *ecdsa.PublicKey:
   555  		if !supportedEllipticCurve(t.Curve) {
   556  			return nil, errors.New("ssh: only P256, P384 and P521 EC keys are supported.")
   557  		}
   558  		sshKey = (*ecdsaPublicKey)(t)
   559  	case *dsa.PublicKey:
   560  		sshKey = (*dsaPublicKey)(t)
   561  	default:
   562  		return nil, fmt.Errorf("ssh: unsupported key type %T", k)
   563  	}
   564  	return sshKey, nil
   565  }
   566  
   567  // ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
   568  // the same keys as ParseRawPrivateKey.
   569  func ParsePrivateKey(pemBytes []byte) (Signer, error) {
   570  	key, err := ParseRawPrivateKey(pemBytes)
   571  	if err != nil {
   572  		return nil, err
   573  	}
   574  
   575  	return NewSignerFromKey(key)
   576  }
   577  
   578  // ParseRawPrivateKey returns a private key from a PEM encoded private key. It
   579  // supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
   580  func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
   581  	block, _ := pem.Decode(pemBytes)
   582  	if block == nil {
   583  		return nil, errors.New("ssh: no key found")
   584  	}
   585  
   586  	switch block.Type {
   587  	case "RSA PRIVATE KEY":
   588  		return x509.ParsePKCS1PrivateKey(block.Bytes)
   589  	case "EC PRIVATE KEY":
   590  		return x509.ParseECPrivateKey(block.Bytes)
   591  	case "DSA PRIVATE KEY":
   592  		return ParseDSAPrivateKey(block.Bytes)
   593  	default:
   594  		return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
   595  	}
   596  }
   597  
   598  // ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
   599  // specified by the OpenSSL DSA man page.
   600  func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
   601  	var k struct {
   602  		Version int
   603  		P       *big.Int
   604  		Q       *big.Int
   605  		G       *big.Int
   606  		Priv    *big.Int
   607  		Pub     *big.Int
   608  	}
   609  	rest, err := asn1.Unmarshal(der, &k)
   610  	if err != nil {
   611  		return nil, errors.New("ssh: failed to parse DSA key: " + err.Error())
   612  	}
   613  	if len(rest) > 0 {
   614  		return nil, errors.New("ssh: garbage after DSA key")
   615  	}
   616  
   617  	return &dsa.PrivateKey{
   618  		PublicKey: dsa.PublicKey{
   619  			Parameters: dsa.Parameters{
   620  				P: k.P,
   621  				Q: k.Q,
   622  				G: k.G,
   623  			},
   624  			Y: k.Priv,
   625  		},
   626  		X: k.Pub,
   627  	}, nil
   628  }