...

Source file src/golang.org/x/crypto/ssh/keys_test.go

Documentation: golang.org/x/crypto/ssh

     1  // Copyright 2014 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/dsa"
    10  	"crypto/ecdsa"
    11  	"crypto/ed25519"
    12  	"crypto/elliptic"
    13  	"crypto/rand"
    14  	"crypto/rsa"
    15  	"crypto/x509"
    16  	"encoding/base64"
    17  	"encoding/hex"
    18  	"encoding/pem"
    19  	"errors"
    20  	"fmt"
    21  	"io"
    22  	"reflect"
    23  	"strings"
    24  	"testing"
    25  
    26  	"golang.org/x/crypto/ssh/testdata"
    27  )
    28  
    29  func rawKey(pub PublicKey) interface{} {
    30  	switch k := pub.(type) {
    31  	case *rsaPublicKey:
    32  		return (*rsa.PublicKey)(k)
    33  	case *dsaPublicKey:
    34  		return (*dsa.PublicKey)(k)
    35  	case *ecdsaPublicKey:
    36  		return (*ecdsa.PublicKey)(k)
    37  	case ed25519PublicKey:
    38  		return (ed25519.PublicKey)(k)
    39  	case *Certificate:
    40  		return k
    41  	}
    42  	panic("unknown key type")
    43  }
    44  
    45  func TestKeyMarshalParse(t *testing.T) {
    46  	for _, priv := range testSigners {
    47  		pub := priv.PublicKey()
    48  		roundtrip, err := ParsePublicKey(pub.Marshal())
    49  		if err != nil {
    50  			t.Errorf("ParsePublicKey(%T): %v", pub, err)
    51  		}
    52  
    53  		k1 := rawKey(pub)
    54  		k2 := rawKey(roundtrip)
    55  
    56  		if !reflect.DeepEqual(k1, k2) {
    57  			t.Errorf("got %#v in roundtrip, want %#v", k2, k1)
    58  		}
    59  	}
    60  }
    61  
    62  func TestUnsupportedCurves(t *testing.T) {
    63  	raw, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
    64  	if err != nil {
    65  		t.Fatalf("GenerateKey: %v", err)
    66  	}
    67  
    68  	if _, err = NewSignerFromKey(raw); err == nil || !strings.Contains(err.Error(), "only P-256") {
    69  		t.Fatalf("NewPrivateKey should not succeed with P-224, got: %v", err)
    70  	}
    71  
    72  	if _, err = NewPublicKey(&raw.PublicKey); err == nil || !strings.Contains(err.Error(), "only P-256") {
    73  		t.Fatalf("NewPublicKey should not succeed with P-224, got: %v", err)
    74  	}
    75  }
    76  
    77  func TestNewPublicKey(t *testing.T) {
    78  	for _, k := range testSigners {
    79  		raw := rawKey(k.PublicKey())
    80  		// Skip certificates, as NewPublicKey does not support them.
    81  		if _, ok := raw.(*Certificate); ok {
    82  			continue
    83  		}
    84  		pub, err := NewPublicKey(raw)
    85  		if err != nil {
    86  			t.Errorf("NewPublicKey(%#v): %v", raw, err)
    87  		}
    88  		if !reflect.DeepEqual(k.PublicKey(), pub) {
    89  			t.Errorf("NewPublicKey(%#v) = %#v, want %#v", raw, pub, k.PublicKey())
    90  		}
    91  	}
    92  }
    93  
    94  func TestKeySignVerify(t *testing.T) {
    95  	for _, priv := range testSigners {
    96  		pub := priv.PublicKey()
    97  
    98  		data := []byte("sign me")
    99  		sig, err := priv.Sign(rand.Reader, data)
   100  		if err != nil {
   101  			t.Fatalf("Sign(%T): %v", priv, err)
   102  		}
   103  
   104  		if err := pub.Verify(data, sig); err != nil {
   105  			t.Errorf("publicKey.Verify(%T): %v", priv, err)
   106  		}
   107  		sig.Blob[5]++
   108  		if err := pub.Verify(data, sig); err == nil {
   109  			t.Errorf("publicKey.Verify on broken sig did not fail")
   110  		}
   111  	}
   112  }
   113  
   114  func TestKeySignWithAlgorithmVerify(t *testing.T) {
   115  	for k, priv := range testSigners {
   116  		if algorithmSigner, ok := priv.(MultiAlgorithmSigner); !ok {
   117  			t.Errorf("Signers %q constructed by ssh package should always implement the MultiAlgorithmSigner interface: %T", k, priv)
   118  		} else {
   119  			pub := priv.PublicKey()
   120  			data := []byte("sign me")
   121  
   122  			signWithAlgTestCase := func(algorithm string, expectedAlg string) {
   123  				sig, err := algorithmSigner.SignWithAlgorithm(rand.Reader, data, algorithm)
   124  				if err != nil {
   125  					t.Fatalf("Sign(%T): %v", priv, err)
   126  				}
   127  				if sig.Format != expectedAlg {
   128  					t.Errorf("signature format did not match requested signature algorithm: %s != %s", sig.Format, expectedAlg)
   129  				}
   130  
   131  				if err := pub.Verify(data, sig); err != nil {
   132  					t.Errorf("publicKey.Verify(%T): %v", priv, err)
   133  				}
   134  				sig.Blob[5]++
   135  				if err := pub.Verify(data, sig); err == nil {
   136  					t.Errorf("publicKey.Verify on broken sig did not fail")
   137  				}
   138  			}
   139  
   140  			// Using the empty string as the algorithm name should result in the same signature format as the algorithm-free Sign method.
   141  			defaultSig, err := priv.Sign(rand.Reader, data)
   142  			if err != nil {
   143  				t.Fatalf("Sign(%T): %v", priv, err)
   144  			}
   145  			signWithAlgTestCase("", defaultSig.Format)
   146  
   147  			// RSA keys are the only ones which currently support more than one signing algorithm
   148  			if pub.Type() == KeyAlgoRSA {
   149  				for _, algorithm := range []string{KeyAlgoRSA, KeyAlgoRSASHA256, KeyAlgoRSASHA512} {
   150  					signWithAlgTestCase(algorithm, algorithm)
   151  				}
   152  			}
   153  		}
   154  	}
   155  }
   156  
   157  func TestKeySignWithShortSignature(t *testing.T) {
   158  	signer := testSigners["rsa"].(AlgorithmSigner)
   159  	pub := signer.PublicKey()
   160  	// Note: data obtained by empirically trying until a result
   161  	// starting with 0 appeared
   162  	tests := []struct {
   163  		algorithm string
   164  		data      []byte
   165  	}{
   166  		{
   167  			algorithm: KeyAlgoRSA,
   168  			data:      []byte("sign me92"),
   169  		},
   170  		{
   171  			algorithm: KeyAlgoRSASHA256,
   172  			data:      []byte("sign me294"),
   173  		},
   174  		{
   175  			algorithm: KeyAlgoRSASHA512,
   176  			data:      []byte("sign me60"),
   177  		},
   178  	}
   179  
   180  	for _, tt := range tests {
   181  		sig, err := signer.SignWithAlgorithm(rand.Reader, tt.data, tt.algorithm)
   182  		if err != nil {
   183  			t.Fatalf("Sign(%T): %v", signer, err)
   184  		}
   185  		if sig.Blob[0] != 0 {
   186  			t.Errorf("%s: Expected signature with a leading 0", tt.algorithm)
   187  		}
   188  		sig.Blob = sig.Blob[1:]
   189  		if err := pub.Verify(tt.data, sig); err != nil {
   190  			t.Errorf("publicKey.Verify(%s): %v", tt.algorithm, err)
   191  		}
   192  	}
   193  }
   194  
   195  func TestParseRSAPrivateKey(t *testing.T) {
   196  	key := testPrivateKeys["rsa"]
   197  
   198  	rsa, ok := key.(*rsa.PrivateKey)
   199  	if !ok {
   200  		t.Fatalf("got %T, want *rsa.PrivateKey", rsa)
   201  	}
   202  
   203  	if err := rsa.Validate(); err != nil {
   204  		t.Errorf("Validate: %v", err)
   205  	}
   206  }
   207  
   208  func TestParseECPrivateKey(t *testing.T) {
   209  	key := testPrivateKeys["ecdsa"]
   210  
   211  	ecKey, ok := key.(*ecdsa.PrivateKey)
   212  	if !ok {
   213  		t.Fatalf("got %T, want *ecdsa.PrivateKey", ecKey)
   214  	}
   215  
   216  	if !validateECPublicKey(ecKey.Curve, ecKey.X, ecKey.Y) {
   217  		t.Fatalf("public key does not validate.")
   218  	}
   219  }
   220  
   221  func TestParseEncryptedPrivateKeysWithPassphrase(t *testing.T) {
   222  	data := []byte("sign me")
   223  	for _, tt := range testdata.PEMEncryptedKeys {
   224  		t.Run(tt.Name, func(t *testing.T) {
   225  			_, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte("incorrect"))
   226  			if err != x509.IncorrectPasswordError {
   227  				t.Errorf("got %v want IncorrectPasswordError", err)
   228  			}
   229  
   230  			s, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte(tt.EncryptionKey))
   231  			if err != nil {
   232  				t.Fatalf("ParsePrivateKeyWithPassphrase returned error: %s", err)
   233  			}
   234  
   235  			sig, err := s.Sign(rand.Reader, data)
   236  			if err != nil {
   237  				t.Fatalf("Signer.Sign: %v", err)
   238  			}
   239  			if err := s.PublicKey().Verify(data, sig); err != nil {
   240  				t.Errorf("Verify failed: %v", err)
   241  			}
   242  
   243  			_, err = ParsePrivateKey(tt.PEMBytes)
   244  			if err == nil {
   245  				t.Fatalf("ParsePrivateKey succeeded, expected an error")
   246  			}
   247  
   248  			if err, ok := err.(*PassphraseMissingError); !ok {
   249  				t.Errorf("got error %q, want PassphraseMissingError", err)
   250  			} else if tt.IncludesPublicKey {
   251  				if err.PublicKey == nil {
   252  					t.Fatalf("expected PassphraseMissingError.PublicKey not to be nil")
   253  				}
   254  				got, want := err.PublicKey.Marshal(), s.PublicKey().Marshal()
   255  				if !bytes.Equal(got, want) {
   256  					t.Errorf("error field %q doesn't match signer public key %q", got, want)
   257  				}
   258  			}
   259  		})
   260  	}
   261  }
   262  
   263  func TestParseEncryptedPrivateKeysWithIncorrectPassphrase(t *testing.T) {
   264  	pem := testdata.PEMEncryptedKeys[0].PEMBytes
   265  	for i := 0; i < 4096; i++ {
   266  		_, err := ParseRawPrivateKeyWithPassphrase(pem, []byte(fmt.Sprintf("%d", i)))
   267  		if !errors.Is(err, x509.IncorrectPasswordError) {
   268  			t.Fatalf("expected error: %v, got: %v", x509.IncorrectPasswordError, err)
   269  		}
   270  	}
   271  }
   272  
   273  func TestParseDSA(t *testing.T) {
   274  	// We actually exercise the ParsePrivateKey codepath here, as opposed to
   275  	// using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go
   276  	// uses.
   277  	s, err := ParsePrivateKey(testdata.PEMBytes["dsa"])
   278  	if err != nil {
   279  		t.Fatalf("ParsePrivateKey returned error: %s", err)
   280  	}
   281  
   282  	data := []byte("sign me")
   283  	sig, err := s.Sign(rand.Reader, data)
   284  	if err != nil {
   285  		t.Fatalf("dsa.Sign: %v", err)
   286  	}
   287  
   288  	if err := s.PublicKey().Verify(data, sig); err != nil {
   289  		t.Errorf("Verify failed: %v", err)
   290  	}
   291  }
   292  
   293  // Tests for authorized_keys parsing.
   294  
   295  // getTestKey returns a public key, and its base64 encoding.
   296  func getTestKey() (PublicKey, string) {
   297  	k := testPublicKeys["rsa"]
   298  
   299  	b := &bytes.Buffer{}
   300  	e := base64.NewEncoder(base64.StdEncoding, b)
   301  	e.Write(k.Marshal())
   302  	e.Close()
   303  
   304  	return k, b.String()
   305  }
   306  
   307  func TestMarshalParsePublicKey(t *testing.T) {
   308  	pub, pubSerialized := getTestKey()
   309  	line := fmt.Sprintf("%s %s user@host", pub.Type(), pubSerialized)
   310  
   311  	authKeys := MarshalAuthorizedKey(pub)
   312  	actualFields := strings.Fields(string(authKeys))
   313  	if len(actualFields) == 0 {
   314  		t.Fatalf("failed authKeys: %v", authKeys)
   315  	}
   316  
   317  	// drop the comment
   318  	expectedFields := strings.Fields(line)[0:2]
   319  
   320  	if !reflect.DeepEqual(actualFields, expectedFields) {
   321  		t.Errorf("got %v, expected %v", actualFields, expectedFields)
   322  	}
   323  
   324  	actPub, _, _, _, err := ParseAuthorizedKey([]byte(line))
   325  	if err != nil {
   326  		t.Fatalf("cannot parse %v: %v", line, err)
   327  	}
   328  	if !reflect.DeepEqual(actPub, pub) {
   329  		t.Errorf("got %v, expected %v", actPub, pub)
   330  	}
   331  }
   332  
   333  func TestMarshalPrivateKey(t *testing.T) {
   334  	tests := []struct {
   335  		name string
   336  	}{
   337  		{"rsa-openssh-format"},
   338  		{"ed25519"},
   339  		{"p256-openssh-format"},
   340  		{"p384-openssh-format"},
   341  		{"p521-openssh-format"},
   342  	}
   343  	for _, tt := range tests {
   344  		t.Run(tt.name, func(t *testing.T) {
   345  			expected, ok := testPrivateKeys[tt.name]
   346  			if !ok {
   347  				t.Fatalf("cannot find key %s", tt.name)
   348  			}
   349  
   350  			block, err := MarshalPrivateKey(expected, "test@golang.org")
   351  			if err != nil {
   352  				t.Fatalf("cannot marshal %s: %v", tt.name, err)
   353  			}
   354  
   355  			key, err := ParseRawPrivateKey(pem.EncodeToMemory(block))
   356  			if err != nil {
   357  				t.Fatalf("cannot parse %s: %v", tt.name, err)
   358  			}
   359  
   360  			if !reflect.DeepEqual(expected, key) {
   361  				t.Errorf("unexpected marshaled key %s", tt.name)
   362  			}
   363  		})
   364  	}
   365  }
   366  
   367  func TestMarshalPrivateKeyWithPassphrase(t *testing.T) {
   368  	tests := []struct {
   369  		name string
   370  	}{
   371  		{"rsa-openssh-format"},
   372  		{"ed25519"},
   373  		{"p256-openssh-format"},
   374  		{"p384-openssh-format"},
   375  		{"p521-openssh-format"},
   376  	}
   377  	for _, tt := range tests {
   378  		t.Run(tt.name, func(t *testing.T) {
   379  			expected, ok := testPrivateKeys[tt.name]
   380  			if !ok {
   381  				t.Fatalf("cannot find key %s", tt.name)
   382  			}
   383  
   384  			block, err := MarshalPrivateKeyWithPassphrase(expected, "test@golang.org", []byte("test-passphrase"))
   385  			if err != nil {
   386  				t.Fatalf("cannot marshal %s: %v", tt.name, err)
   387  			}
   388  
   389  			key, err := ParseRawPrivateKeyWithPassphrase(pem.EncodeToMemory(block), []byte("test-passphrase"))
   390  			if err != nil {
   391  				t.Fatalf("cannot parse %s: %v", tt.name, err)
   392  			}
   393  
   394  			if !reflect.DeepEqual(expected, key) {
   395  				t.Errorf("unexpected marshaled key %s", tt.name)
   396  			}
   397  		})
   398  	}
   399  }
   400  
   401  type testAuthResult struct {
   402  	pubKey   PublicKey
   403  	options  []string
   404  	comments string
   405  	rest     string
   406  	ok       bool
   407  }
   408  
   409  func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []testAuthResult) {
   410  	rest := authKeys
   411  	var values []testAuthResult
   412  	for len(rest) > 0 {
   413  		var r testAuthResult
   414  		var err error
   415  		r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest)
   416  		r.ok = (err == nil)
   417  		t.Log(err)
   418  		r.rest = string(rest)
   419  		values = append(values, r)
   420  	}
   421  
   422  	if !reflect.DeepEqual(values, expected) {
   423  		t.Errorf("got %#v, expected %#v", values, expected)
   424  	}
   425  }
   426  
   427  func TestAuthorizedKeyBasic(t *testing.T) {
   428  	pub, pubSerialized := getTestKey()
   429  	line := "ssh-rsa " + pubSerialized + " user@host"
   430  	testAuthorizedKeys(t, []byte(line),
   431  		[]testAuthResult{
   432  			{pub, nil, "user@host", "", true},
   433  		})
   434  }
   435  
   436  func TestAuth(t *testing.T) {
   437  	pub, pubSerialized := getTestKey()
   438  	authWithOptions := []string{
   439  		`# comments to ignore before any keys...`,
   440  		``,
   441  		`env="HOME=/home/root",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`,
   442  		`# comments to ignore, along with a blank line`,
   443  		``,
   444  		`env="HOME=/home/root2" ssh-rsa ` + pubSerialized + ` user2@host2`,
   445  		``,
   446  		`# more comments, plus a invalid entry`,
   447  		`ssh-rsa data-that-will-not-parse user@host3`,
   448  	}
   449  	for _, eol := range []string{"\n", "\r\n"} {
   450  		authOptions := strings.Join(authWithOptions, eol)
   451  		rest2 := strings.Join(authWithOptions[3:], eol)
   452  		rest3 := strings.Join(authWithOptions[6:], eol)
   453  		testAuthorizedKeys(t, []byte(authOptions), []testAuthResult{
   454  			{pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true},
   455  			{pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true},
   456  			{nil, nil, "", "", false},
   457  		})
   458  	}
   459  }
   460  
   461  func TestAuthWithQuotedSpaceInEnv(t *testing.T) {
   462  	pub, pubSerialized := getTestKey()
   463  	authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`)
   464  	testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []testAuthResult{
   465  		{pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true},
   466  	})
   467  }
   468  
   469  func TestAuthWithQuotedCommaInEnv(t *testing.T) {
   470  	pub, pubSerialized := getTestKey()
   471  	authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + `   user@host`)
   472  	testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []testAuthResult{
   473  		{pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true},
   474  	})
   475  }
   476  
   477  func TestAuthWithQuotedQuoteInEnv(t *testing.T) {
   478  	pub, pubSerialized := getTestKey()
   479  	authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + `   user@host`)
   480  	authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`)
   481  	testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []testAuthResult{
   482  		{pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true},
   483  	})
   484  
   485  	testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []testAuthResult{
   486  		{pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true},
   487  	})
   488  }
   489  
   490  func TestAuthWithInvalidSpace(t *testing.T) {
   491  	_, pubSerialized := getTestKey()
   492  	authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host
   493  #more to follow but still no valid keys`)
   494  	testAuthorizedKeys(t, []byte(authWithInvalidSpace), []testAuthResult{
   495  		{nil, nil, "", "", false},
   496  	})
   497  }
   498  
   499  func TestAuthWithMissingQuote(t *testing.T) {
   500  	pub, pubSerialized := getTestKey()
   501  	authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host
   502  env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`)
   503  
   504  	testAuthorizedKeys(t, []byte(authWithMissingQuote), []testAuthResult{
   505  		{pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true},
   506  	})
   507  }
   508  
   509  func TestInvalidEntry(t *testing.T) {
   510  	authInvalid := []byte(`ssh-rsa`)
   511  	_, _, _, _, err := ParseAuthorizedKey(authInvalid)
   512  	if err == nil {
   513  		t.Errorf("got valid entry for %q", authInvalid)
   514  	}
   515  }
   516  
   517  var knownHostsParseTests = []struct {
   518  	input string
   519  	err   string
   520  
   521  	marker  string
   522  	comment string
   523  	hosts   []string
   524  	rest    string
   525  }{
   526  	{
   527  		"",
   528  		"EOF",
   529  
   530  		"", "", nil, "",
   531  	},
   532  	{
   533  		"# Just a comment",
   534  		"EOF",
   535  
   536  		"", "", nil, "",
   537  	},
   538  	{
   539  		"   \t   ",
   540  		"EOF",
   541  
   542  		"", "", nil, "",
   543  	},
   544  	{
   545  		"localhost ssh-rsa {RSAPUB}",
   546  		"",
   547  
   548  		"", "", []string{"localhost"}, "",
   549  	},
   550  	{
   551  		"localhost\tssh-rsa {RSAPUB}",
   552  		"",
   553  
   554  		"", "", []string{"localhost"}, "",
   555  	},
   556  	{
   557  		"localhost\tssh-rsa {RSAPUB}\tcomment comment",
   558  		"",
   559  
   560  		"", "comment comment", []string{"localhost"}, "",
   561  	},
   562  	{
   563  		"localhost\tssh-rsa {RSAPUB}\tcomment comment\n",
   564  		"",
   565  
   566  		"", "comment comment", []string{"localhost"}, "",
   567  	},
   568  	{
   569  		"localhost\tssh-rsa {RSAPUB}\tcomment comment\r\n",
   570  		"",
   571  
   572  		"", "comment comment", []string{"localhost"}, "",
   573  	},
   574  	{
   575  		"localhost\tssh-rsa {RSAPUB}\tcomment comment\r\nnext line",
   576  		"",
   577  
   578  		"", "comment comment", []string{"localhost"}, "next line",
   579  	},
   580  	{
   581  		"localhost,[host2:123]\tssh-rsa {RSAPUB}\tcomment comment",
   582  		"",
   583  
   584  		"", "comment comment", []string{"localhost", "[host2:123]"}, "",
   585  	},
   586  	{
   587  		"@marker \tlocalhost,[host2:123]\tssh-rsa {RSAPUB}",
   588  		"",
   589  
   590  		"marker", "", []string{"localhost", "[host2:123]"}, "",
   591  	},
   592  	{
   593  		"@marker \tlocalhost,[host2:123]\tssh-rsa aabbccdd",
   594  		"short read",
   595  
   596  		"", "", nil, "",
   597  	},
   598  }
   599  
   600  func TestKnownHostsParsing(t *testing.T) {
   601  	rsaPub, rsaPubSerialized := getTestKey()
   602  
   603  	for i, test := range knownHostsParseTests {
   604  		var expectedKey PublicKey
   605  		const rsaKeyToken = "{RSAPUB}"
   606  
   607  		input := test.input
   608  		if strings.Contains(input, rsaKeyToken) {
   609  			expectedKey = rsaPub
   610  			input = strings.Replace(test.input, rsaKeyToken, rsaPubSerialized, -1)
   611  		}
   612  
   613  		marker, hosts, pubKey, comment, rest, err := ParseKnownHosts([]byte(input))
   614  		if err != nil {
   615  			if len(test.err) == 0 {
   616  				t.Errorf("#%d: unexpectedly failed with %q", i, err)
   617  			} else if !strings.Contains(err.Error(), test.err) {
   618  				t.Errorf("#%d: expected error containing %q, but got %q", i, test.err, err)
   619  			}
   620  			continue
   621  		} else if len(test.err) != 0 {
   622  			t.Errorf("#%d: succeeded but expected error including %q", i, test.err)
   623  			continue
   624  		}
   625  
   626  		if !reflect.DeepEqual(expectedKey, pubKey) {
   627  			t.Errorf("#%d: expected key %#v, but got %#v", i, expectedKey, pubKey)
   628  		}
   629  
   630  		if marker != test.marker {
   631  			t.Errorf("#%d: expected marker %q, but got %q", i, test.marker, marker)
   632  		}
   633  
   634  		if comment != test.comment {
   635  			t.Errorf("#%d: expected comment %q, but got %q", i, test.comment, comment)
   636  		}
   637  
   638  		if !reflect.DeepEqual(test.hosts, hosts) {
   639  			t.Errorf("#%d: expected hosts %#v, but got %#v", i, test.hosts, hosts)
   640  		}
   641  
   642  		if rest := string(rest); rest != test.rest {
   643  			t.Errorf("#%d: expected remaining input to be %q, but got %q", i, test.rest, rest)
   644  		}
   645  	}
   646  }
   647  
   648  func TestFingerprintLegacyMD5(t *testing.T) {
   649  	pub, _ := getTestKey()
   650  	fingerprint := FingerprintLegacyMD5(pub)
   651  	want := "b7:ef:d3:d5:89:29:52:96:9f:df:47:41:4d:15:37:f4" // ssh-keygen -lf -E md5 rsa
   652  	if fingerprint != want {
   653  		t.Errorf("got fingerprint %q want %q", fingerprint, want)
   654  	}
   655  }
   656  
   657  func TestFingerprintSHA256(t *testing.T) {
   658  	pub, _ := getTestKey()
   659  	fingerprint := FingerprintSHA256(pub)
   660  	want := "SHA256:fi5+D7UmDZDE9Q2sAVvvlpcQSIakN4DERdINgXd2AnE" // ssh-keygen -lf rsa
   661  	if fingerprint != want {
   662  		t.Errorf("got fingerprint %q want %q", fingerprint, want)
   663  	}
   664  }
   665  
   666  func TestInvalidKeys(t *testing.T) {
   667  	keyTypes := []string{
   668  		"RSA PRIVATE KEY",
   669  		"PRIVATE KEY",
   670  		"EC PRIVATE KEY",
   671  		"DSA PRIVATE KEY",
   672  		"OPENSSH PRIVATE KEY",
   673  	}
   674  
   675  	for _, keyType := range keyTypes {
   676  		for _, dataLen := range []int{0, 1, 2, 5, 10, 20} {
   677  			data := make([]byte, dataLen)
   678  			if _, err := io.ReadFull(rand.Reader, data); err != nil {
   679  				t.Fatal(err)
   680  			}
   681  
   682  			var buf bytes.Buffer
   683  			pem.Encode(&buf, &pem.Block{
   684  				Type:  keyType,
   685  				Bytes: data,
   686  			})
   687  
   688  			// This test is just to ensure that the function
   689  			// doesn't panic so the return value is ignored.
   690  			ParseRawPrivateKey(buf.Bytes())
   691  		}
   692  	}
   693  }
   694  
   695  func TestSKKeys(t *testing.T) {
   696  	for _, d := range testdata.SKData {
   697  		pk, _, _, _, err := ParseAuthorizedKey(d.PubKey)
   698  		if err != nil {
   699  			t.Fatalf("parseAuthorizedKey returned error: %v", err)
   700  		}
   701  
   702  		sigBuf := make([]byte, hex.DecodedLen(len(d.HexSignature)))
   703  		if _, err := hex.Decode(sigBuf, d.HexSignature); err != nil {
   704  			t.Fatalf("hex.Decode() failed: %v", err)
   705  		}
   706  
   707  		dataBuf := make([]byte, hex.DecodedLen(len(d.HexData)))
   708  		if _, err := hex.Decode(dataBuf, d.HexData); err != nil {
   709  			t.Fatalf("hex.Decode() failed: %v", err)
   710  		}
   711  
   712  		sig, _, ok := parseSignature(sigBuf)
   713  		if !ok {
   714  			t.Fatalf("parseSignature(%v) failed", sigBuf)
   715  		}
   716  
   717  		// Test that good data and signature pass verification
   718  		if err := pk.Verify(dataBuf, sig); err != nil {
   719  			t.Errorf("%s: PublicKey.Verify(%v, %v) failed: %v", d.Name, dataBuf, sig, err)
   720  		}
   721  
   722  		// Invalid data being passed in
   723  		invalidData := []byte("INVALID DATA")
   724  		if err := pk.Verify(invalidData, sig); err == nil {
   725  			t.Errorf("%s with invalid data: PublicKey.Verify(%v, %v) passed unexpectedly", d.Name, invalidData, sig)
   726  		}
   727  
   728  		// Change byte in blob to corrup signature
   729  		sig.Blob[5] = byte('A')
   730  		// Corrupted data being passed in
   731  		if err := pk.Verify(dataBuf, sig); err == nil {
   732  			t.Errorf("%s with corrupted signature: PublicKey.Verify(%v, %v) passed unexpectedly", d.Name, dataBuf, sig)
   733  		}
   734  	}
   735  }
   736  
   737  func TestNewSignerWithAlgos(t *testing.T) {
   738  	algorithSigner, ok := testSigners["rsa"].(AlgorithmSigner)
   739  	if !ok {
   740  		t.Fatal("rsa test signer does not implement the AlgorithmSigner interface")
   741  	}
   742  	_, err := NewSignerWithAlgorithms(algorithSigner, nil)
   743  	if err == nil {
   744  		t.Error("signer with algos created with no algorithms")
   745  	}
   746  
   747  	_, err = NewSignerWithAlgorithms(algorithSigner, []string{KeyAlgoED25519})
   748  	if err == nil {
   749  		t.Error("signer with algos created with invalid algorithms")
   750  	}
   751  
   752  	_, err = NewSignerWithAlgorithms(algorithSigner, []string{CertAlgoRSASHA256v01})
   753  	if err == nil {
   754  		t.Error("signer with algos created with certificate algorithms")
   755  	}
   756  
   757  	mas, err := NewSignerWithAlgorithms(algorithSigner, []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512})
   758  	if err != nil {
   759  		t.Errorf("unable to create signer with valid algorithms: %v", err)
   760  	}
   761  
   762  	_, err = NewSignerWithAlgorithms(mas, []string{KeyAlgoRSA})
   763  	if err == nil {
   764  		t.Error("signer with algos created with restricted algorithms")
   765  	}
   766  }
   767  
   768  func TestCryptoPublicKey(t *testing.T) {
   769  	for _, priv := range testSigners {
   770  		p1 := priv.PublicKey()
   771  		key, ok := p1.(CryptoPublicKey)
   772  		if !ok {
   773  			continue
   774  		}
   775  		p2, err := NewPublicKey(key.CryptoPublicKey())
   776  		if err != nil {
   777  			t.Fatalf("NewPublicKey(CryptoPublicKey) failed for %s, got: %v", p1.Type(), err)
   778  		}
   779  		if !reflect.DeepEqual(p1, p2) {
   780  			t.Errorf("got %#v in NewPublicKey, want %#v", p2, p1)
   781  		}
   782  	}
   783  	for _, d := range testdata.SKData {
   784  		p1, _, _, _, err := ParseAuthorizedKey(d.PubKey)
   785  		if err != nil {
   786  			t.Fatalf("parseAuthorizedKey returned error: %v", err)
   787  		}
   788  		k1, ok := p1.(CryptoPublicKey)
   789  		if !ok {
   790  			t.Fatalf("%T does not implement CryptoPublicKey", p1)
   791  		}
   792  
   793  		var p2 PublicKey
   794  		switch pub := k1.CryptoPublicKey().(type) {
   795  		case *ecdsa.PublicKey:
   796  			p2 = &skECDSAPublicKey{
   797  				application: "ssh:",
   798  				PublicKey:   *pub,
   799  			}
   800  		case ed25519.PublicKey:
   801  			p2 = &skEd25519PublicKey{
   802  				application: "ssh:",
   803  				PublicKey:   pub,
   804  			}
   805  		default:
   806  			t.Fatalf("unexpected type %T from CryptoPublicKey()", pub)
   807  		}
   808  		if !reflect.DeepEqual(p1, p2) {
   809  			t.Errorf("got %#v, want %#v", p2, p1)
   810  		}
   811  	}
   812  }
   813  

View as plain text