...

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 TestParseRSAPrivateKey(t *testing.T) {
   158  	key := testPrivateKeys["rsa"]
   159  
   160  	rsa, ok := key.(*rsa.PrivateKey)
   161  	if !ok {
   162  		t.Fatalf("got %T, want *rsa.PrivateKey", rsa)
   163  	}
   164  
   165  	if err := rsa.Validate(); err != nil {
   166  		t.Errorf("Validate: %v", err)
   167  	}
   168  }
   169  
   170  func TestParseECPrivateKey(t *testing.T) {
   171  	key := testPrivateKeys["ecdsa"]
   172  
   173  	ecKey, ok := key.(*ecdsa.PrivateKey)
   174  	if !ok {
   175  		t.Fatalf("got %T, want *ecdsa.PrivateKey", ecKey)
   176  	}
   177  
   178  	if !validateECPublicKey(ecKey.Curve, ecKey.X, ecKey.Y) {
   179  		t.Fatalf("public key does not validate.")
   180  	}
   181  }
   182  
   183  func TestParseEncryptedPrivateKeysWithPassphrase(t *testing.T) {
   184  	data := []byte("sign me")
   185  	for _, tt := range testdata.PEMEncryptedKeys {
   186  		t.Run(tt.Name, func(t *testing.T) {
   187  			_, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte("incorrect"))
   188  			if err != x509.IncorrectPasswordError {
   189  				t.Errorf("got %v want IncorrectPasswordError", err)
   190  			}
   191  
   192  			s, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte(tt.EncryptionKey))
   193  			if err != nil {
   194  				t.Fatalf("ParsePrivateKeyWithPassphrase returned error: %s", err)
   195  			}
   196  
   197  			sig, err := s.Sign(rand.Reader, data)
   198  			if err != nil {
   199  				t.Fatalf("Signer.Sign: %v", err)
   200  			}
   201  			if err := s.PublicKey().Verify(data, sig); err != nil {
   202  				t.Errorf("Verify failed: %v", err)
   203  			}
   204  
   205  			_, err = ParsePrivateKey(tt.PEMBytes)
   206  			if err == nil {
   207  				t.Fatalf("ParsePrivateKey succeeded, expected an error")
   208  			}
   209  
   210  			if err, ok := err.(*PassphraseMissingError); !ok {
   211  				t.Errorf("got error %q, want PassphraseMissingError", err)
   212  			} else if tt.IncludesPublicKey {
   213  				if err.PublicKey == nil {
   214  					t.Fatalf("expected PassphraseMissingError.PublicKey not to be nil")
   215  				}
   216  				got, want := err.PublicKey.Marshal(), s.PublicKey().Marshal()
   217  				if !bytes.Equal(got, want) {
   218  					t.Errorf("error field %q doesn't match signer public key %q", got, want)
   219  				}
   220  			}
   221  		})
   222  	}
   223  }
   224  
   225  func TestParseEncryptedPrivateKeysWithIncorrectPassphrase(t *testing.T) {
   226  	pem := testdata.PEMEncryptedKeys[0].PEMBytes
   227  	for i := 0; i < 4096; i++ {
   228  		_, err := ParseRawPrivateKeyWithPassphrase(pem, []byte(fmt.Sprintf("%d", i)))
   229  		if !errors.Is(err, x509.IncorrectPasswordError) {
   230  			t.Fatalf("expected error: %v, got: %v", x509.IncorrectPasswordError, err)
   231  		}
   232  	}
   233  }
   234  
   235  func TestParseDSA(t *testing.T) {
   236  	// We actually exercise the ParsePrivateKey codepath here, as opposed to
   237  	// using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go
   238  	// uses.
   239  	s, err := ParsePrivateKey(testdata.PEMBytes["dsa"])
   240  	if err != nil {
   241  		t.Fatalf("ParsePrivateKey returned error: %s", err)
   242  	}
   243  
   244  	data := []byte("sign me")
   245  	sig, err := s.Sign(rand.Reader, data)
   246  	if err != nil {
   247  		t.Fatalf("dsa.Sign: %v", err)
   248  	}
   249  
   250  	if err := s.PublicKey().Verify(data, sig); err != nil {
   251  		t.Errorf("Verify failed: %v", err)
   252  	}
   253  }
   254  
   255  // Tests for authorized_keys parsing.
   256  
   257  // getTestKey returns a public key, and its base64 encoding.
   258  func getTestKey() (PublicKey, string) {
   259  	k := testPublicKeys["rsa"]
   260  
   261  	b := &bytes.Buffer{}
   262  	e := base64.NewEncoder(base64.StdEncoding, b)
   263  	e.Write(k.Marshal())
   264  	e.Close()
   265  
   266  	return k, b.String()
   267  }
   268  
   269  func TestMarshalParsePublicKey(t *testing.T) {
   270  	pub, pubSerialized := getTestKey()
   271  	line := fmt.Sprintf("%s %s user@host", pub.Type(), pubSerialized)
   272  
   273  	authKeys := MarshalAuthorizedKey(pub)
   274  	actualFields := strings.Fields(string(authKeys))
   275  	if len(actualFields) == 0 {
   276  		t.Fatalf("failed authKeys: %v", authKeys)
   277  	}
   278  
   279  	// drop the comment
   280  	expectedFields := strings.Fields(line)[0:2]
   281  
   282  	if !reflect.DeepEqual(actualFields, expectedFields) {
   283  		t.Errorf("got %v, expected %v", actualFields, expectedFields)
   284  	}
   285  
   286  	actPub, _, _, _, err := ParseAuthorizedKey([]byte(line))
   287  	if err != nil {
   288  		t.Fatalf("cannot parse %v: %v", line, err)
   289  	}
   290  	if !reflect.DeepEqual(actPub, pub) {
   291  		t.Errorf("got %v, expected %v", actPub, pub)
   292  	}
   293  }
   294  
   295  func TestMarshalPrivateKey(t *testing.T) {
   296  	tests := []struct {
   297  		name string
   298  	}{
   299  		{"rsa-openssh-format"},
   300  		{"ed25519"},
   301  		{"p256-openssh-format"},
   302  		{"p384-openssh-format"},
   303  		{"p521-openssh-format"},
   304  	}
   305  	for _, tt := range tests {
   306  		t.Run(tt.name, func(t *testing.T) {
   307  			expected, ok := testPrivateKeys[tt.name]
   308  			if !ok {
   309  				t.Fatalf("cannot find key %s", tt.name)
   310  			}
   311  
   312  			block, err := MarshalPrivateKey(expected, "test@golang.org")
   313  			if err != nil {
   314  				t.Fatalf("cannot marshal %s: %v", tt.name, err)
   315  			}
   316  
   317  			key, err := ParseRawPrivateKey(pem.EncodeToMemory(block))
   318  			if err != nil {
   319  				t.Fatalf("cannot parse %s: %v", tt.name, err)
   320  			}
   321  
   322  			if !reflect.DeepEqual(expected, key) {
   323  				t.Errorf("unexpected marshaled key %s", tt.name)
   324  			}
   325  		})
   326  	}
   327  }
   328  
   329  func TestMarshalPrivateKeyWithPassphrase(t *testing.T) {
   330  	tests := []struct {
   331  		name string
   332  	}{
   333  		{"rsa-openssh-format"},
   334  		{"ed25519"},
   335  		{"p256-openssh-format"},
   336  		{"p384-openssh-format"},
   337  		{"p521-openssh-format"},
   338  	}
   339  	for _, tt := range tests {
   340  		t.Run(tt.name, func(t *testing.T) {
   341  			expected, ok := testPrivateKeys[tt.name]
   342  			if !ok {
   343  				t.Fatalf("cannot find key %s", tt.name)
   344  			}
   345  
   346  			block, err := MarshalPrivateKeyWithPassphrase(expected, "test@golang.org", []byte("test-passphrase"))
   347  			if err != nil {
   348  				t.Fatalf("cannot marshal %s: %v", tt.name, err)
   349  			}
   350  
   351  			key, err := ParseRawPrivateKeyWithPassphrase(pem.EncodeToMemory(block), []byte("test-passphrase"))
   352  			if err != nil {
   353  				t.Fatalf("cannot parse %s: %v", tt.name, err)
   354  			}
   355  
   356  			if !reflect.DeepEqual(expected, key) {
   357  				t.Errorf("unexpected marshaled key %s", tt.name)
   358  			}
   359  		})
   360  	}
   361  }
   362  
   363  type testAuthResult struct {
   364  	pubKey   PublicKey
   365  	options  []string
   366  	comments string
   367  	rest     string
   368  	ok       bool
   369  }
   370  
   371  func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []testAuthResult) {
   372  	rest := authKeys
   373  	var values []testAuthResult
   374  	for len(rest) > 0 {
   375  		var r testAuthResult
   376  		var err error
   377  		r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest)
   378  		r.ok = (err == nil)
   379  		t.Log(err)
   380  		r.rest = string(rest)
   381  		values = append(values, r)
   382  	}
   383  
   384  	if !reflect.DeepEqual(values, expected) {
   385  		t.Errorf("got %#v, expected %#v", values, expected)
   386  	}
   387  }
   388  
   389  func TestAuthorizedKeyBasic(t *testing.T) {
   390  	pub, pubSerialized := getTestKey()
   391  	line := "ssh-rsa " + pubSerialized + " user@host"
   392  	testAuthorizedKeys(t, []byte(line),
   393  		[]testAuthResult{
   394  			{pub, nil, "user@host", "", true},
   395  		})
   396  }
   397  
   398  func TestAuth(t *testing.T) {
   399  	pub, pubSerialized := getTestKey()
   400  	authWithOptions := []string{
   401  		`# comments to ignore before any keys...`,
   402  		``,
   403  		`env="HOME=/home/root",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`,
   404  		`# comments to ignore, along with a blank line`,
   405  		``,
   406  		`env="HOME=/home/root2" ssh-rsa ` + pubSerialized + ` user2@host2`,
   407  		``,
   408  		`# more comments, plus a invalid entry`,
   409  		`ssh-rsa data-that-will-not-parse user@host3`,
   410  	}
   411  	for _, eol := range []string{"\n", "\r\n"} {
   412  		authOptions := strings.Join(authWithOptions, eol)
   413  		rest2 := strings.Join(authWithOptions[3:], eol)
   414  		rest3 := strings.Join(authWithOptions[6:], eol)
   415  		testAuthorizedKeys(t, []byte(authOptions), []testAuthResult{
   416  			{pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true},
   417  			{pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true},
   418  			{nil, nil, "", "", false},
   419  		})
   420  	}
   421  }
   422  
   423  func TestAuthWithQuotedSpaceInEnv(t *testing.T) {
   424  	pub, pubSerialized := getTestKey()
   425  	authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`)
   426  	testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []testAuthResult{
   427  		{pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true},
   428  	})
   429  }
   430  
   431  func TestAuthWithQuotedCommaInEnv(t *testing.T) {
   432  	pub, pubSerialized := getTestKey()
   433  	authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + `   user@host`)
   434  	testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []testAuthResult{
   435  		{pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true},
   436  	})
   437  }
   438  
   439  func TestAuthWithQuotedQuoteInEnv(t *testing.T) {
   440  	pub, pubSerialized := getTestKey()
   441  	authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + `   user@host`)
   442  	authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`)
   443  	testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []testAuthResult{
   444  		{pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true},
   445  	})
   446  
   447  	testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []testAuthResult{
   448  		{pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true},
   449  	})
   450  }
   451  
   452  func TestAuthWithInvalidSpace(t *testing.T) {
   453  	_, pubSerialized := getTestKey()
   454  	authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host
   455  #more to follow but still no valid keys`)
   456  	testAuthorizedKeys(t, []byte(authWithInvalidSpace), []testAuthResult{
   457  		{nil, nil, "", "", false},
   458  	})
   459  }
   460  
   461  func TestAuthWithMissingQuote(t *testing.T) {
   462  	pub, pubSerialized := getTestKey()
   463  	authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host
   464  env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`)
   465  
   466  	testAuthorizedKeys(t, []byte(authWithMissingQuote), []testAuthResult{
   467  		{pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true},
   468  	})
   469  }
   470  
   471  func TestInvalidEntry(t *testing.T) {
   472  	authInvalid := []byte(`ssh-rsa`)
   473  	_, _, _, _, err := ParseAuthorizedKey(authInvalid)
   474  	if err == nil {
   475  		t.Errorf("got valid entry for %q", authInvalid)
   476  	}
   477  }
   478  
   479  var knownHostsParseTests = []struct {
   480  	input string
   481  	err   string
   482  
   483  	marker  string
   484  	comment string
   485  	hosts   []string
   486  	rest    string
   487  }{
   488  	{
   489  		"",
   490  		"EOF",
   491  
   492  		"", "", nil, "",
   493  	},
   494  	{
   495  		"# Just a comment",
   496  		"EOF",
   497  
   498  		"", "", nil, "",
   499  	},
   500  	{
   501  		"   \t   ",
   502  		"EOF",
   503  
   504  		"", "", nil, "",
   505  	},
   506  	{
   507  		"localhost ssh-rsa {RSAPUB}",
   508  		"",
   509  
   510  		"", "", []string{"localhost"}, "",
   511  	},
   512  	{
   513  		"localhost\tssh-rsa {RSAPUB}",
   514  		"",
   515  
   516  		"", "", []string{"localhost"}, "",
   517  	},
   518  	{
   519  		"localhost\tssh-rsa {RSAPUB}\tcomment comment",
   520  		"",
   521  
   522  		"", "comment comment", []string{"localhost"}, "",
   523  	},
   524  	{
   525  		"localhost\tssh-rsa {RSAPUB}\tcomment comment\n",
   526  		"",
   527  
   528  		"", "comment comment", []string{"localhost"}, "",
   529  	},
   530  	{
   531  		"localhost\tssh-rsa {RSAPUB}\tcomment comment\r\n",
   532  		"",
   533  
   534  		"", "comment comment", []string{"localhost"}, "",
   535  	},
   536  	{
   537  		"localhost\tssh-rsa {RSAPUB}\tcomment comment\r\nnext line",
   538  		"",
   539  
   540  		"", "comment comment", []string{"localhost"}, "next line",
   541  	},
   542  	{
   543  		"localhost,[host2:123]\tssh-rsa {RSAPUB}\tcomment comment",
   544  		"",
   545  
   546  		"", "comment comment", []string{"localhost", "[host2:123]"}, "",
   547  	},
   548  	{
   549  		"@marker \tlocalhost,[host2:123]\tssh-rsa {RSAPUB}",
   550  		"",
   551  
   552  		"marker", "", []string{"localhost", "[host2:123]"}, "",
   553  	},
   554  	{
   555  		"@marker \tlocalhost,[host2:123]\tssh-rsa aabbccdd",
   556  		"short read",
   557  
   558  		"", "", nil, "",
   559  	},
   560  }
   561  
   562  func TestKnownHostsParsing(t *testing.T) {
   563  	rsaPub, rsaPubSerialized := getTestKey()
   564  
   565  	for i, test := range knownHostsParseTests {
   566  		var expectedKey PublicKey
   567  		const rsaKeyToken = "{RSAPUB}"
   568  
   569  		input := test.input
   570  		if strings.Contains(input, rsaKeyToken) {
   571  			expectedKey = rsaPub
   572  			input = strings.Replace(test.input, rsaKeyToken, rsaPubSerialized, -1)
   573  		}
   574  
   575  		marker, hosts, pubKey, comment, rest, err := ParseKnownHosts([]byte(input))
   576  		if err != nil {
   577  			if len(test.err) == 0 {
   578  				t.Errorf("#%d: unexpectedly failed with %q", i, err)
   579  			} else if !strings.Contains(err.Error(), test.err) {
   580  				t.Errorf("#%d: expected error containing %q, but got %q", i, test.err, err)
   581  			}
   582  			continue
   583  		} else if len(test.err) != 0 {
   584  			t.Errorf("#%d: succeeded but expected error including %q", i, test.err)
   585  			continue
   586  		}
   587  
   588  		if !reflect.DeepEqual(expectedKey, pubKey) {
   589  			t.Errorf("#%d: expected key %#v, but got %#v", i, expectedKey, pubKey)
   590  		}
   591  
   592  		if marker != test.marker {
   593  			t.Errorf("#%d: expected marker %q, but got %q", i, test.marker, marker)
   594  		}
   595  
   596  		if comment != test.comment {
   597  			t.Errorf("#%d: expected comment %q, but got %q", i, test.comment, comment)
   598  		}
   599  
   600  		if !reflect.DeepEqual(test.hosts, hosts) {
   601  			t.Errorf("#%d: expected hosts %#v, but got %#v", i, test.hosts, hosts)
   602  		}
   603  
   604  		if rest := string(rest); rest != test.rest {
   605  			t.Errorf("#%d: expected remaining input to be %q, but got %q", i, test.rest, rest)
   606  		}
   607  	}
   608  }
   609  
   610  func TestFingerprintLegacyMD5(t *testing.T) {
   611  	pub, _ := getTestKey()
   612  	fingerprint := FingerprintLegacyMD5(pub)
   613  	want := "fb:61:6d:1a:e3:f0:95:45:3c:a0:79:be:4a:93:63:66" // ssh-keygen -lf -E md5 rsa
   614  	if fingerprint != want {
   615  		t.Errorf("got fingerprint %q want %q", fingerprint, want)
   616  	}
   617  }
   618  
   619  func TestFingerprintSHA256(t *testing.T) {
   620  	pub, _ := getTestKey()
   621  	fingerprint := FingerprintSHA256(pub)
   622  	want := "SHA256:Anr3LjZK8YVpjrxu79myrW9Hrb/wpcMNpVvTq/RcBm8" // ssh-keygen -lf rsa
   623  	if fingerprint != want {
   624  		t.Errorf("got fingerprint %q want %q", fingerprint, want)
   625  	}
   626  }
   627  
   628  func TestInvalidKeys(t *testing.T) {
   629  	keyTypes := []string{
   630  		"RSA PRIVATE KEY",
   631  		"PRIVATE KEY",
   632  		"EC PRIVATE KEY",
   633  		"DSA PRIVATE KEY",
   634  		"OPENSSH PRIVATE KEY",
   635  	}
   636  
   637  	for _, keyType := range keyTypes {
   638  		for _, dataLen := range []int{0, 1, 2, 5, 10, 20} {
   639  			data := make([]byte, dataLen)
   640  			if _, err := io.ReadFull(rand.Reader, data); err != nil {
   641  				t.Fatal(err)
   642  			}
   643  
   644  			var buf bytes.Buffer
   645  			pem.Encode(&buf, &pem.Block{
   646  				Type:  keyType,
   647  				Bytes: data,
   648  			})
   649  
   650  			// This test is just to ensure that the function
   651  			// doesn't panic so the return value is ignored.
   652  			ParseRawPrivateKey(buf.Bytes())
   653  		}
   654  	}
   655  }
   656  
   657  func TestSKKeys(t *testing.T) {
   658  	for _, d := range testdata.SKData {
   659  		pk, _, _, _, err := ParseAuthorizedKey(d.PubKey)
   660  		if err != nil {
   661  			t.Fatalf("parseAuthorizedKey returned error: %v", err)
   662  		}
   663  
   664  		sigBuf := make([]byte, hex.DecodedLen(len(d.HexSignature)))
   665  		if _, err := hex.Decode(sigBuf, d.HexSignature); err != nil {
   666  			t.Fatalf("hex.Decode() failed: %v", err)
   667  		}
   668  
   669  		dataBuf := make([]byte, hex.DecodedLen(len(d.HexData)))
   670  		if _, err := hex.Decode(dataBuf, d.HexData); err != nil {
   671  			t.Fatalf("hex.Decode() failed: %v", err)
   672  		}
   673  
   674  		sig, _, ok := parseSignature(sigBuf)
   675  		if !ok {
   676  			t.Fatalf("parseSignature(%v) failed", sigBuf)
   677  		}
   678  
   679  		// Test that good data and signature pass verification
   680  		if err := pk.Verify(dataBuf, sig); err != nil {
   681  			t.Errorf("%s: PublicKey.Verify(%v, %v) failed: %v", d.Name, dataBuf, sig, err)
   682  		}
   683  
   684  		// Invalid data being passed in
   685  		invalidData := []byte("INVALID DATA")
   686  		if err := pk.Verify(invalidData, sig); err == nil {
   687  			t.Errorf("%s with invalid data: PublicKey.Verify(%v, %v) passed unexpectedly", d.Name, invalidData, sig)
   688  		}
   689  
   690  		// Change byte in blob to corrup signature
   691  		sig.Blob[5] = byte('A')
   692  		// Corrupted data being passed in
   693  		if err := pk.Verify(dataBuf, sig); err == nil {
   694  			t.Errorf("%s with corrupted signature: PublicKey.Verify(%v, %v) passed unexpectedly", d.Name, dataBuf, sig)
   695  		}
   696  	}
   697  }
   698  
   699  func TestNewSignerWithAlgos(t *testing.T) {
   700  	algorithSigner, ok := testSigners["rsa"].(AlgorithmSigner)
   701  	if !ok {
   702  		t.Fatal("rsa test signer does not implement the AlgorithmSigner interface")
   703  	}
   704  	_, err := NewSignerWithAlgorithms(algorithSigner, nil)
   705  	if err == nil {
   706  		t.Error("signer with algos created with no algorithms")
   707  	}
   708  
   709  	_, err = NewSignerWithAlgorithms(algorithSigner, []string{KeyAlgoED25519})
   710  	if err == nil {
   711  		t.Error("signer with algos created with invalid algorithms")
   712  	}
   713  
   714  	_, err = NewSignerWithAlgorithms(algorithSigner, []string{CertAlgoRSASHA256v01})
   715  	if err == nil {
   716  		t.Error("signer with algos created with certificate algorithms")
   717  	}
   718  
   719  	mas, err := NewSignerWithAlgorithms(algorithSigner, []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512})
   720  	if err != nil {
   721  		t.Errorf("unable to create signer with valid algorithms: %v", err)
   722  	}
   723  
   724  	_, err = NewSignerWithAlgorithms(mas, []string{KeyAlgoRSA})
   725  	if err == nil {
   726  		t.Error("signer with algos created with restricted algorithms")
   727  	}
   728  }
   729  

View as plain text