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