github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/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 dsaPublicKey dsa.PublicKey
   271  
   272  func (r *dsaPublicKey) Type() string {
   273  	return "ssh-dss"
   274  }
   275  
   276  // parseDSA parses an DSA key according to RFC 4253, section 6.6.
   277  func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
   278  	var w struct {
   279  		P, Q, G, Y *big.Int
   280  		Rest       []byte `ssh:"rest"`
   281  	}
   282  	if err := Unmarshal(in, &w); err != nil {
   283  		return nil, nil, err
   284  	}
   285  
   286  	key := &dsaPublicKey{
   287  		Parameters: dsa.Parameters{
   288  			P: w.P,
   289  			Q: w.Q,
   290  			G: w.G,
   291  		},
   292  		Y: w.Y,
   293  	}
   294  	return key, w.Rest, nil
   295  }
   296  
   297  func (k *dsaPublicKey) Marshal() []byte {
   298  	w := struct {
   299  		Name       string
   300  		P, Q, G, Y *big.Int
   301  	}{
   302  		k.Type(),
   303  		k.P,
   304  		k.Q,
   305  		k.G,
   306  		k.Y,
   307  	}
   308  
   309  	return Marshal(&w)
   310  }
   311  
   312  func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
   313  	if sig.Format != k.Type() {
   314  		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
   315  	}
   316  	h := crypto.SHA1.New()
   317  	h.Write(data)
   318  	digest := h.Sum(nil)
   319  
   320  	// Per RFC 4253, section 6.6,
   321  	// The value for 'dss_signature_blob' is encoded as a string containing
   322  	// r, followed by s (which are 160-bit integers, without lengths or
   323  	// padding, unsigned, and in network byte order).
   324  	// For DSS purposes, sig.Blob should be exactly 40 bytes in length.
   325  	if len(sig.Blob) != 40 {
   326  		return errors.New("ssh: DSA signature parse error")
   327  	}
   328  	r := new(big.Int).SetBytes(sig.Blob[:20])
   329  	s := new(big.Int).SetBytes(sig.Blob[20:])
   330  	if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) {
   331  		return nil
   332  	}
   333  	return errors.New("ssh: signature did not verify")
   334  }
   335  
   336  type dsaPrivateKey struct {
   337  	*dsa.PrivateKey
   338  }
   339  
   340  func (k *dsaPrivateKey) PublicKey() PublicKey {
   341  	return (*dsaPublicKey)(&k.PrivateKey.PublicKey)
   342  }
   343  
   344  func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
   345  	h := crypto.SHA1.New()
   346  	h.Write(data)
   347  	digest := h.Sum(nil)
   348  	r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
   349  	if err != nil {
   350  		return nil, err
   351  	}
   352  
   353  	sig := make([]byte, 40)
   354  	rb := r.Bytes()
   355  	sb := s.Bytes()
   356  
   357  	copy(sig[20-len(rb):20], rb)
   358  	copy(sig[40-len(sb):], sb)
   359  
   360  	return &Signature{
   361  		Format: k.PublicKey().Type(),
   362  		Blob:   sig,
   363  	}, nil
   364  }
   365  
   366  type ecdsaPublicKey ecdsa.PublicKey
   367  
   368  func (key *ecdsaPublicKey) Type() string {
   369  	return "ecdsa-sha2-" + key.nistID()
   370  }
   371  
   372  func (key *ecdsaPublicKey) nistID() string {
   373  	switch key.Params().BitSize {
   374  	case 256:
   375  		return "nistp256"
   376  	case 384:
   377  		return "nistp384"
   378  	case 521:
   379  		return "nistp521"
   380  	}
   381  	panic("ssh: unsupported ecdsa key size")
   382  }
   383  
   384  func supportedEllipticCurve(curve elliptic.Curve) bool {
   385  	return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
   386  }
   387  
   388  // ecHash returns the hash to match the given elliptic curve, see RFC
   389  // 5656, section 6.2.1
   390  func ecHash(curve elliptic.Curve) crypto.Hash {
   391  	bitSize := curve.Params().BitSize
   392  	switch {
   393  	case bitSize <= 256:
   394  		return crypto.SHA256
   395  	case bitSize <= 384:
   396  		return crypto.SHA384
   397  	}
   398  	return crypto.SHA512
   399  }
   400  
   401  // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
   402  func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
   403  	var w struct {
   404  		Curve    string
   405  		KeyBytes []byte
   406  		Rest     []byte `ssh:"rest"`
   407  	}
   408  
   409  	if err := Unmarshal(in, &w); err != nil {
   410  		return nil, nil, err
   411  	}
   412  
   413  	key := new(ecdsa.PublicKey)
   414  
   415  	switch w.Curve {
   416  	case "nistp256":
   417  		key.Curve = elliptic.P256()
   418  	case "nistp384":
   419  		key.Curve = elliptic.P384()
   420  	case "nistp521":
   421  		key.Curve = elliptic.P521()
   422  	default:
   423  		return nil, nil, errors.New("ssh: unsupported curve")
   424  	}
   425  
   426  	key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
   427  	if key.X == nil || key.Y == nil {
   428  		return nil, nil, errors.New("ssh: invalid curve point")
   429  	}
   430  	return (*ecdsaPublicKey)(key), w.Rest, nil
   431  }
   432  
   433  func (key *ecdsaPublicKey) Marshal() []byte {
   434  	// See RFC 5656, section 3.1.
   435  	keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y)
   436  	w := struct {
   437  		Name string
   438  		ID   string
   439  		Key  []byte
   440  	}{
   441  		key.Type(),
   442  		key.nistID(),
   443  		keyBytes,
   444  	}
   445  
   446  	return Marshal(&w)
   447  }
   448  
   449  func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
   450  	if sig.Format != key.Type() {
   451  		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
   452  	}
   453  
   454  	h := ecHash(key.Curve).New()
   455  	h.Write(data)
   456  	digest := h.Sum(nil)
   457  
   458  	// Per RFC 5656, section 3.1.2,
   459  	// The ecdsa_signature_blob value has the following specific encoding:
   460  	//    mpint    r
   461  	//    mpint    s
   462  	var ecSig struct {
   463  		R *big.Int
   464  		S *big.Int
   465  	}
   466  
   467  	if err := Unmarshal(sig.Blob, &ecSig); err != nil {
   468  		return err
   469  	}
   470  
   471  	if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) {
   472  		return nil
   473  	}
   474  	return errors.New("ssh: signature did not verify")
   475  }
   476  
   477  // NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
   478  // *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding
   479  // Signer instance. ECDSA keys must use P-256, P-384 or P-521.
   480  func NewSignerFromKey(key interface{}) (Signer, error) {
   481  	switch key := key.(type) {
   482  	case crypto.Signer:
   483  		return NewSignerFromSigner(key)
   484  	case *dsa.PrivateKey:
   485  		return &dsaPrivateKey{key}, nil
   486  	default:
   487  		return nil, fmt.Errorf("ssh: unsupported key type %T", key)
   488  	}
   489  }
   490  
   491  type wrappedSigner struct {
   492  	signer crypto.Signer
   493  	pubKey PublicKey
   494  }
   495  
   496  // NewSignerFromSigner takes any crypto.Signer implementation and
   497  // returns a corresponding Signer interface. This can be used, for
   498  // example, with keys kept in hardware modules.
   499  func NewSignerFromSigner(signer crypto.Signer) (Signer, error) {
   500  	pubKey, err := NewPublicKey(signer.Public())
   501  	if err != nil {
   502  		return nil, err
   503  	}
   504  
   505  	return &wrappedSigner{signer, pubKey}, nil
   506  }
   507  
   508  func (s *wrappedSigner) PublicKey() PublicKey {
   509  	return s.pubKey
   510  }
   511  
   512  func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
   513  	var hashFunc crypto.Hash
   514  
   515  	switch key := s.pubKey.(type) {
   516  	case *rsaPublicKey, *dsaPublicKey:
   517  		hashFunc = crypto.SHA1
   518  	case *ecdsaPublicKey:
   519  		hashFunc = ecHash(key.Curve)
   520  	default:
   521  		return nil, fmt.Errorf("ssh: unsupported key type %T", key)
   522  	}
   523  
   524  	h := hashFunc.New()
   525  	h.Write(data)
   526  	digest := h.Sum(nil)
   527  
   528  	signature, err := s.signer.Sign(rand, digest, hashFunc)
   529  	if err != nil {
   530  		return nil, err
   531  	}
   532  
   533  	// crypto.Signer.Sign is expected to return an ASN.1-encoded signature
   534  	// for ECDSA and DSA, but that's not the encoding expected by SSH, so
   535  	// re-encode.
   536  	switch s.pubKey.(type) {
   537  	case *ecdsaPublicKey, *dsaPublicKey:
   538  		type asn1Signature struct {
   539  			R, S *big.Int
   540  		}
   541  		asn1Sig := new(asn1Signature)
   542  		_, err := asn1.Unmarshal(signature, asn1Sig)
   543  		if err != nil {
   544  			return nil, err
   545  		}
   546  
   547  		switch s.pubKey.(type) {
   548  		case *ecdsaPublicKey:
   549  			signature = Marshal(asn1Sig)
   550  
   551  		case *dsaPublicKey:
   552  			signature = make([]byte, 40)
   553  			r := asn1Sig.R.Bytes()
   554  			s := asn1Sig.S.Bytes()
   555  			copy(signature[20-len(r):20], r)
   556  			copy(signature[40-len(s):40], s)
   557  		}
   558  	}
   559  
   560  	return &Signature{
   561  		Format: s.pubKey.Type(),
   562  		Blob:   signature,
   563  	}, nil
   564  }
   565  
   566  // NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or
   567  // any other crypto.Signer and returns a corresponding Signer instance. ECDSA
   568  // keys must use P-256, P-384 or P-521.
   569  func NewPublicKey(key interface{}) (PublicKey, error) {
   570  	switch key := key.(type) {
   571  	case *rsa.PublicKey:
   572  		return (*rsaPublicKey)(key), nil
   573  	case *ecdsa.PublicKey:
   574  		if !supportedEllipticCurve(key.Curve) {
   575  			return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported.")
   576  		}
   577  		return (*ecdsaPublicKey)(key), nil
   578  	case *dsa.PublicKey:
   579  		return (*dsaPublicKey)(key), nil
   580  	default:
   581  		return nil, fmt.Errorf("ssh: unsupported key type %T", key)
   582  	}
   583  }
   584  
   585  // ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
   586  // the same keys as ParseRawPrivateKey.
   587  func ParsePrivateKey(pemBytes []byte) (Signer, error) {
   588  	key, err := ParseRawPrivateKey(pemBytes)
   589  	if err != nil {
   590  		return nil, err
   591  	}
   592  
   593  	return NewSignerFromKey(key)
   594  }
   595  
   596  // ParseRawPrivateKey returns a private key from a PEM encoded private key. It
   597  // supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
   598  func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
   599  	block, _ := pem.Decode(pemBytes)
   600  	if block == nil {
   601  		return nil, errors.New("ssh: no key found")
   602  	}
   603  
   604  	switch block.Type {
   605  	case "RSA PRIVATE KEY":
   606  		return x509.ParsePKCS1PrivateKey(block.Bytes)
   607  	case "EC PRIVATE KEY":
   608  		return x509.ParseECPrivateKey(block.Bytes)
   609  	case "DSA PRIVATE KEY":
   610  		return ParseDSAPrivateKey(block.Bytes)
   611  	default:
   612  		return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
   613  	}
   614  }
   615  
   616  // ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
   617  // specified by the OpenSSL DSA man page.
   618  func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
   619  	var k struct {
   620  		Version int
   621  		P       *big.Int
   622  		Q       *big.Int
   623  		G       *big.Int
   624  		Priv    *big.Int
   625  		Pub     *big.Int
   626  	}
   627  	rest, err := asn1.Unmarshal(der, &k)
   628  	if err != nil {
   629  		return nil, errors.New("ssh: failed to parse DSA key: " + err.Error())
   630  	}
   631  	if len(rest) > 0 {
   632  		return nil, errors.New("ssh: garbage after DSA key")
   633  	}
   634  
   635  	return &dsa.PrivateKey{
   636  		PublicKey: dsa.PublicKey{
   637  			Parameters: dsa.Parameters{
   638  				P: k.P,
   639  				Q: k.Q,
   640  				G: k.G,
   641  			},
   642  			Y: k.Priv,
   643  		},
   644  		X: k.Pub,
   645  	}, nil
   646  }