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