github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/lang/funcs/crypto_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package funcs
     5  
     6  import (
     7  	"fmt"
     8  	"testing"
     9  
    10  	"github.com/zclconf/go-cty/cty"
    11  	"golang.org/x/crypto/bcrypt"
    12  )
    13  
    14  func TestUUID(t *testing.T) {
    15  	result, err := UUID()
    16  	if err != nil {
    17  		t.Fatal(err)
    18  	}
    19  
    20  	resultStr := result.AsString()
    21  	if got, want := len(resultStr), 36; got != want {
    22  		t.Errorf("wrong result length %d; want %d", got, want)
    23  	}
    24  }
    25  
    26  func TestUUIDV5(t *testing.T) {
    27  	tests := []struct {
    28  		Namespace cty.Value
    29  		Name      cty.Value
    30  		Want      cty.Value
    31  		Err       bool
    32  	}{
    33  		{
    34  			cty.StringVal("dns"),
    35  			cty.StringVal("tada"),
    36  			cty.StringVal("faa898db-9b9d-5b75-86a9-149e7bb8e3b8"),
    37  			false,
    38  		},
    39  		{
    40  			cty.StringVal("url"),
    41  			cty.StringVal("tada"),
    42  			cty.StringVal("2c1ff6b4-211f-577e-94de-d978b0caa16e"),
    43  			false,
    44  		},
    45  		{
    46  			cty.StringVal("oid"),
    47  			cty.StringVal("tada"),
    48  			cty.StringVal("61eeea26-5176-5288-87fc-232d6ed30d2f"),
    49  			false,
    50  		},
    51  		{
    52  			cty.StringVal("x500"),
    53  			cty.StringVal("tada"),
    54  			cty.StringVal("7e12415e-f7c9-57c3-9e43-52dc9950d264"),
    55  			false,
    56  		},
    57  		{
    58  			cty.StringVal("6ba7b810-9dad-11d1-80b4-00c04fd430c8"),
    59  			cty.StringVal("tada"),
    60  			cty.StringVal("faa898db-9b9d-5b75-86a9-149e7bb8e3b8"),
    61  			false,
    62  		},
    63  		{
    64  			cty.StringVal("tada"),
    65  			cty.StringVal("tada"),
    66  			cty.UnknownVal(cty.String),
    67  			true,
    68  		},
    69  	}
    70  
    71  	for _, test := range tests {
    72  		t.Run(fmt.Sprintf("uuidv5(%#v, %#v)", test.Namespace, test.Name), func(t *testing.T) {
    73  			got, err := UUIDV5(test.Namespace, test.Name)
    74  
    75  			if test.Err {
    76  				if err == nil {
    77  					t.Fatal("succeeded; want error")
    78  				}
    79  				return
    80  			} else if err != nil {
    81  				t.Fatalf("unexpected error: %s", err)
    82  			}
    83  
    84  			if !got.RawEquals(test.Want) {
    85  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
    86  			}
    87  		})
    88  	}
    89  }
    90  
    91  func TestBase64Sha256(t *testing.T) {
    92  	tests := []struct {
    93  		String cty.Value
    94  		Want   cty.Value
    95  		Err    bool
    96  	}{
    97  		{
    98  			cty.StringVal("test"),
    99  			cty.StringVal("n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="),
   100  			false,
   101  		},
   102  		// This would differ because we're base64-encoding hex represantiation, not raw bytes.
   103  		// base64encode(sha256("test")) =
   104  		// "OWY4NmQwODE4ODRjN2Q2NTlhMmZlYWEwYzU1YWQwMTVhM2JmNGYxYjJiMGI4MjJjZDE1ZDZjMTViMGYwMGEwOA=="
   105  	}
   106  
   107  	for _, test := range tests {
   108  		t.Run(fmt.Sprintf("base64sha256(%#v)", test.String), func(t *testing.T) {
   109  			got, err := Base64Sha256(test.String)
   110  
   111  			if test.Err {
   112  				if err == nil {
   113  					t.Fatal("succeeded; want error")
   114  				}
   115  				return
   116  			} else if err != nil {
   117  				t.Fatalf("unexpected error: %s", err)
   118  			}
   119  
   120  			if !got.RawEquals(test.Want) {
   121  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   122  			}
   123  		})
   124  	}
   125  }
   126  
   127  func TestFileBase64Sha256(t *testing.T) {
   128  	tests := []struct {
   129  		Path cty.Value
   130  		Want cty.Value
   131  		Err  bool
   132  	}{
   133  		{
   134  			cty.StringVal("testdata/hello.txt"),
   135  			cty.StringVal("pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4="),
   136  			false,
   137  		},
   138  		{
   139  			cty.StringVal("testdata/icon.png"),
   140  			cty.StringVal("47U1q9IZW093SmAzdC820Skpn8vHPvc8szud/Y3ezpo="),
   141  			false,
   142  		},
   143  		{
   144  			cty.StringVal("testdata/missing"),
   145  			cty.NilVal,
   146  			true, // no file exists
   147  		},
   148  	}
   149  
   150  	fileSHA256 := MakeFileBase64Sha256Func(".")
   151  
   152  	for _, test := range tests {
   153  		t.Run(fmt.Sprintf("filebase64sha256(%#v)", test.Path), func(t *testing.T) {
   154  			got, err := fileSHA256.Call([]cty.Value{test.Path})
   155  
   156  			if test.Err {
   157  				if err == nil {
   158  					t.Fatal("succeeded; want error")
   159  				}
   160  				return
   161  			} else if err != nil {
   162  				t.Fatalf("unexpected error: %s", err)
   163  			}
   164  
   165  			if !got.RawEquals(test.Want) {
   166  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   167  			}
   168  		})
   169  	}
   170  }
   171  
   172  func TestBase64Sha512(t *testing.T) {
   173  	tests := []struct {
   174  		String cty.Value
   175  		Want   cty.Value
   176  		Err    bool
   177  	}{
   178  		{
   179  			cty.StringVal("test"),
   180  			cty.StringVal("7iaw3Ur350mqGo7jwQrpkj9hiYB3Lkc/iBml1JQODbJ6wYX4oOHV+E+IvIh/1nsUNzLDBMxfqa2Ob1f1ACio/w=="),
   181  			false,
   182  		},
   183  		// This would differ because we're base64-encoding hex represantiation, not raw bytes
   184  		// base64encode(sha512("test")) =
   185  		// "OZWUyNmIwZGQ0YWY3ZTc0OWFhMWE4ZWUzYzEwYWU5OTIzZjYxODk4MDc3MmU0NzNmODgxOWE1ZDQ5NDBlMGRiMjdhYzE4NWY4YTBlMWQ1Zjg0Zjg4YmM4ODdmZDY3YjE0MzczMmMzMDRjYzVmYTlhZDhlNmY1N2Y1MDAyOGE4ZmY="
   186  	}
   187  
   188  	for _, test := range tests {
   189  		t.Run(fmt.Sprintf("base64sha512(%#v)", test.String), func(t *testing.T) {
   190  			got, err := Base64Sha512(test.String)
   191  
   192  			if test.Err {
   193  				if err == nil {
   194  					t.Fatal("succeeded; want error")
   195  				}
   196  				return
   197  			} else if err != nil {
   198  				t.Fatalf("unexpected error: %s", err)
   199  			}
   200  
   201  			if !got.RawEquals(test.Want) {
   202  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   203  			}
   204  		})
   205  	}
   206  }
   207  
   208  func TestFileBase64Sha512(t *testing.T) {
   209  	tests := []struct {
   210  		Path cty.Value
   211  		Want cty.Value
   212  		Err  bool
   213  	}{
   214  		{
   215  			cty.StringVal("testdata/hello.txt"),
   216  			cty.StringVal("LHT9F+2v2A6ER7DUZ0HuJDt+t03SFJoKsbkkb7MDgvJ+hT2FhXGeDmfL2g2qj1FnEGRhXWRa4nrLFb+xRH9Fmw=="),
   217  			false,
   218  		},
   219  		{
   220  			cty.StringVal("testdata/icon.png"),
   221  			cty.StringVal("wSInO/tKEOaLGCAY2h/7gtLWMpzyLJ0ijFh95JTpYrPzXQYgviAdL9ZgpD9EAte8On+drvhFvjIFsfQUwxbNPQ=="),
   222  			false,
   223  		},
   224  		{
   225  			cty.StringVal("testdata/missing"),
   226  			cty.NilVal,
   227  			true, // no file exists
   228  		},
   229  	}
   230  
   231  	fileSHA512 := MakeFileBase64Sha512Func(".")
   232  
   233  	for _, test := range tests {
   234  		t.Run(fmt.Sprintf("filebase64sha512(%#v)", test.Path), func(t *testing.T) {
   235  			got, err := fileSHA512.Call([]cty.Value{test.Path})
   236  
   237  			if test.Err {
   238  				if err == nil {
   239  					t.Fatal("succeeded; want error")
   240  				}
   241  				return
   242  			} else if err != nil {
   243  				t.Fatalf("unexpected error: %s", err)
   244  			}
   245  
   246  			if !got.RawEquals(test.Want) {
   247  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   248  			}
   249  		})
   250  	}
   251  }
   252  
   253  func TestBcrypt(t *testing.T) {
   254  	// single variable test
   255  	p, err := Bcrypt(cty.StringVal("test"))
   256  	if err != nil {
   257  		t.Fatalf("err: %s", err)
   258  	}
   259  
   260  	err = bcrypt.CompareHashAndPassword([]byte(p.AsString()), []byte("test"))
   261  	if err != nil {
   262  		t.Fatalf("Error comparing hash and password: %s", err)
   263  	}
   264  
   265  	// testing with two parameters
   266  	p, err = Bcrypt(cty.StringVal("test"), cty.NumberIntVal(5))
   267  	if err != nil {
   268  		t.Fatalf("err: %s", err)
   269  	}
   270  
   271  	err = bcrypt.CompareHashAndPassword([]byte(p.AsString()), []byte("test"))
   272  	if err != nil {
   273  		t.Fatalf("Error comparing hash and password: %s", err)
   274  	}
   275  
   276  	// Negative test for more than two parameters
   277  	_, err = Bcrypt(cty.StringVal("test"), cty.NumberIntVal(10), cty.NumberIntVal(11))
   278  	if err == nil {
   279  		t.Fatal("succeeded; want error")
   280  	}
   281  }
   282  
   283  func TestMd5(t *testing.T) {
   284  	tests := []struct {
   285  		String cty.Value
   286  		Want   cty.Value
   287  		Err    bool
   288  	}{
   289  		{
   290  			cty.StringVal("tada"),
   291  			cty.StringVal("ce47d07243bb6eaf5e1322c81baf9bbf"),
   292  			false,
   293  		},
   294  		{ // Confirm that we're not trimming any whitespaces
   295  			cty.StringVal(" tada "),
   296  			cty.StringVal("aadf191a583e53062de2d02c008141c4"),
   297  			false,
   298  		},
   299  		{ // We accept empty string too
   300  			cty.StringVal(""),
   301  			cty.StringVal("d41d8cd98f00b204e9800998ecf8427e"),
   302  			false,
   303  		},
   304  	}
   305  
   306  	for _, test := range tests {
   307  		t.Run(fmt.Sprintf("md5(%#v)", test.String), func(t *testing.T) {
   308  			got, err := Md5(test.String)
   309  
   310  			if test.Err {
   311  				if err == nil {
   312  					t.Fatal("succeeded; want error")
   313  				}
   314  				return
   315  			} else if err != nil {
   316  				t.Fatalf("unexpected error: %s", err)
   317  			}
   318  
   319  			if !got.RawEquals(test.Want) {
   320  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   321  			}
   322  		})
   323  	}
   324  }
   325  
   326  func TestFileMD5(t *testing.T) {
   327  	tests := []struct {
   328  		Path cty.Value
   329  		Want cty.Value
   330  		Err  bool
   331  	}{
   332  		{
   333  			cty.StringVal("testdata/hello.txt"),
   334  			cty.StringVal("b10a8db164e0754105b7a99be72e3fe5"),
   335  			false,
   336  		},
   337  		{
   338  			cty.StringVal("testdata/icon.png"),
   339  			cty.StringVal("d7e6c283185a1078c58213beadca98b0"),
   340  			false,
   341  		},
   342  		{
   343  			cty.StringVal("testdata/missing"),
   344  			cty.NilVal,
   345  			true, // no file exists
   346  		},
   347  	}
   348  
   349  	fileMD5 := MakeFileMd5Func(".")
   350  
   351  	for _, test := range tests {
   352  		t.Run(fmt.Sprintf("filemd5(%#v)", test.Path), func(t *testing.T) {
   353  			got, err := fileMD5.Call([]cty.Value{test.Path})
   354  
   355  			if test.Err {
   356  				if err == nil {
   357  					t.Fatal("succeeded; want error")
   358  				}
   359  				return
   360  			} else if err != nil {
   361  				t.Fatalf("unexpected error: %s", err)
   362  			}
   363  
   364  			if !got.RawEquals(test.Want) {
   365  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   366  			}
   367  		})
   368  	}
   369  }
   370  
   371  func TestRsaDecrypt(t *testing.T) {
   372  	tests := []struct {
   373  		Ciphertext cty.Value
   374  		Privatekey cty.Value
   375  		Want       cty.Value
   376  		Err        string
   377  	}{
   378  		// Base-64 encoded cipher decrypts correctly
   379  		{
   380  			cty.StringVal(CipherBase64),
   381  			cty.StringVal(PrivateKey),
   382  			cty.StringVal("message"),
   383  			"",
   384  		},
   385  		// OpenSSH key format
   386  		{
   387  			cty.StringVal(CipherBase64),
   388  			cty.StringVal(OpenSSHPrivateKey),
   389  			cty.StringVal("message"),
   390  			"",
   391  		},
   392  		// Wrong key
   393  		{
   394  			cty.StringVal(CipherBase64),
   395  			cty.StringVal(WrongPrivateKey),
   396  			cty.UnknownVal(cty.String),
   397  			"failed to decrypt: crypto/rsa: decryption error",
   398  		},
   399  		// Bad key
   400  		{
   401  			cty.StringVal(CipherBase64),
   402  			cty.StringVal(BadPrivateKey),
   403  			cty.UnknownVal(cty.String),
   404  			"invalid ASN1 data in the given private key: data truncated",
   405  		},
   406  		// Empty key
   407  		{
   408  			cty.StringVal(CipherBase64),
   409  			cty.StringVal(""),
   410  			cty.UnknownVal(cty.String),
   411  			"invalid private key: ssh: no key found",
   412  		},
   413  		// Bad ciphertext
   414  		{
   415  			cty.StringVal("bad"),
   416  			cty.StringVal(PrivateKey),
   417  			cty.UnknownVal(cty.String),
   418  			`failed to decode input "bad": cipher text must be base64-encoded`,
   419  		},
   420  		// Empty ciphertext
   421  		{
   422  			cty.StringVal(""),
   423  			cty.StringVal(PrivateKey),
   424  			cty.UnknownVal(cty.String),
   425  			"failed to decrypt: crypto/rsa: decryption error",
   426  		},
   427  	}
   428  	for _, test := range tests {
   429  		t.Run(fmt.Sprintf("RsaDecrypt(%#v, %#v)", test.Ciphertext, test.Privatekey), func(t *testing.T) {
   430  			got, err := RsaDecrypt(test.Ciphertext, test.Privatekey)
   431  
   432  			if test.Err != "" {
   433  				if err == nil {
   434  					t.Fatal("succeeded; want error")
   435  				} else if err.Error() != test.Err {
   436  					t.Fatalf("wrong error\ngot:  %s\nwant: %s", err.Error(), test.Err)
   437  				}
   438  				return
   439  			} else if err != nil {
   440  				t.Fatalf("unexpected error: %s", err)
   441  			}
   442  
   443  			if !got.RawEquals(test.Want) {
   444  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   445  			}
   446  		})
   447  	}
   448  }
   449  
   450  func TestSha1(t *testing.T) {
   451  	tests := []struct {
   452  		String cty.Value
   453  		Want   cty.Value
   454  		Err    bool
   455  	}{
   456  		{
   457  			cty.StringVal("test"),
   458  			cty.StringVal("a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"),
   459  			false,
   460  		},
   461  	}
   462  
   463  	for _, test := range tests {
   464  		t.Run(fmt.Sprintf("sha1(%#v)", test.String), func(t *testing.T) {
   465  			got, err := Sha1(test.String)
   466  
   467  			if test.Err {
   468  				if err == nil {
   469  					t.Fatal("succeeded; want error")
   470  				}
   471  				return
   472  			} else if err != nil {
   473  				t.Fatalf("unexpected error: %s", err)
   474  			}
   475  
   476  			if !got.RawEquals(test.Want) {
   477  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   478  			}
   479  		})
   480  	}
   481  }
   482  
   483  func TestFileSHA1(t *testing.T) {
   484  	tests := []struct {
   485  		Path cty.Value
   486  		Want cty.Value
   487  		Err  bool
   488  	}{
   489  		{
   490  			cty.StringVal("testdata/hello.txt"),
   491  			cty.StringVal("0a4d55a8d778e5022fab701977c5d840bbc486d0"),
   492  			false,
   493  		},
   494  		{
   495  			cty.StringVal("testdata/icon.png"),
   496  			cty.StringVal("2821bcc8379e1bd6f4f31b1e6a1fbb204b4a8be8"),
   497  			false,
   498  		},
   499  		{
   500  			cty.StringVal("testdata/missing"),
   501  			cty.NilVal,
   502  			true, // no file exists
   503  		},
   504  	}
   505  
   506  	fileSHA1 := MakeFileSha1Func(".")
   507  
   508  	for _, test := range tests {
   509  		t.Run(fmt.Sprintf("filesha1(%#v)", test.Path), func(t *testing.T) {
   510  			got, err := fileSHA1.Call([]cty.Value{test.Path})
   511  
   512  			if test.Err {
   513  				if err == nil {
   514  					t.Fatal("succeeded; want error")
   515  				}
   516  				return
   517  			} else if err != nil {
   518  				t.Fatalf("unexpected error: %s", err)
   519  			}
   520  
   521  			if !got.RawEquals(test.Want) {
   522  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   523  			}
   524  		})
   525  	}
   526  }
   527  
   528  func TestSha256(t *testing.T) {
   529  	tests := []struct {
   530  		String cty.Value
   531  		Want   cty.Value
   532  		Err    bool
   533  	}{
   534  		{
   535  			cty.StringVal("test"),
   536  			cty.StringVal("9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"),
   537  			false,
   538  		},
   539  	}
   540  
   541  	for _, test := range tests {
   542  		t.Run(fmt.Sprintf("sha256(%#v)", test.String), func(t *testing.T) {
   543  			got, err := Sha256(test.String)
   544  
   545  			if test.Err {
   546  				if err == nil {
   547  					t.Fatal("succeeded; want error")
   548  				}
   549  				return
   550  			} else if err != nil {
   551  				t.Fatalf("unexpected error: %s", err)
   552  			}
   553  
   554  			if !got.RawEquals(test.Want) {
   555  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   556  			}
   557  		})
   558  	}
   559  }
   560  
   561  func TestFileSHA256(t *testing.T) {
   562  	tests := []struct {
   563  		Path cty.Value
   564  		Want cty.Value
   565  		Err  bool
   566  	}{
   567  		{
   568  			cty.StringVal("testdata/hello.txt"),
   569  			cty.StringVal("a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"),
   570  			false,
   571  		},
   572  		{
   573  			cty.StringVal("testdata/icon.png"),
   574  			cty.StringVal("e3b535abd2195b4f774a6033742f36d129299fcbc73ef73cb33b9dfd8ddece9a"),
   575  			false,
   576  		},
   577  		{
   578  			cty.StringVal("testdata/missing"),
   579  			cty.NilVal,
   580  			true, // no file exists
   581  		},
   582  	}
   583  
   584  	fileSHA256 := MakeFileSha256Func(".")
   585  
   586  	for _, test := range tests {
   587  		t.Run(fmt.Sprintf("filesha256(%#v)", test.Path), func(t *testing.T) {
   588  			got, err := fileSHA256.Call([]cty.Value{test.Path})
   589  
   590  			if test.Err {
   591  				if err == nil {
   592  					t.Fatal("succeeded; want error")
   593  				}
   594  				return
   595  			} else if err != nil {
   596  				t.Fatalf("unexpected error: %s", err)
   597  			}
   598  
   599  			if !got.RawEquals(test.Want) {
   600  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   601  			}
   602  		})
   603  	}
   604  }
   605  
   606  func TestSha512(t *testing.T) {
   607  	tests := []struct {
   608  		String cty.Value
   609  		Want   cty.Value
   610  		Err    bool
   611  	}{
   612  		{
   613  			cty.StringVal("test"),
   614  			cty.StringVal("ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"),
   615  			false,
   616  		},
   617  	}
   618  
   619  	for _, test := range tests {
   620  		t.Run(fmt.Sprintf("sha512(%#v)", test.String), func(t *testing.T) {
   621  			got, err := Sha512(test.String)
   622  
   623  			if test.Err {
   624  				if err == nil {
   625  					t.Fatal("succeeded; want error")
   626  				}
   627  				return
   628  			} else if err != nil {
   629  				t.Fatalf("unexpected error: %s", err)
   630  			}
   631  
   632  			if !got.RawEquals(test.Want) {
   633  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   634  			}
   635  		})
   636  	}
   637  }
   638  
   639  func TestFileSHA512(t *testing.T) {
   640  	tests := []struct {
   641  		Path cty.Value
   642  		Want cty.Value
   643  		Err  bool
   644  	}{
   645  		{
   646  			cty.StringVal("testdata/hello.txt"),
   647  			cty.StringVal("2c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b"),
   648  			false,
   649  		},
   650  		{
   651  			cty.StringVal("testdata/icon.png"),
   652  			cty.StringVal("c122273bfb4a10e68b182018da1ffb82d2d6329cf22c9d228c587de494e962b3f35d0620be201d2fd660a43f4402d7bc3a7f9daef845be3205b1f414c316cd3d"),
   653  			false,
   654  		},
   655  		{
   656  			cty.StringVal("testdata/missing"),
   657  			cty.NilVal,
   658  			true, // no file exists
   659  		},
   660  	}
   661  
   662  	fileSHA512 := MakeFileSha512Func(".")
   663  
   664  	for _, test := range tests {
   665  		t.Run(fmt.Sprintf("filesha512(%#v)", test.Path), func(t *testing.T) {
   666  			got, err := fileSHA512.Call([]cty.Value{test.Path})
   667  
   668  			if test.Err {
   669  				if err == nil {
   670  					t.Fatal("succeeded; want error")
   671  				}
   672  				return
   673  			} else if err != nil {
   674  				t.Fatalf("unexpected error: %s", err)
   675  			}
   676  
   677  			if !got.RawEquals(test.Want) {
   678  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
   679  			}
   680  		})
   681  	}
   682  }
   683  
   684  const (
   685  	CipherBase64 = "eczGaDhXDbOFRZGhjx2etVzWbRqWDlmq0bvNt284JHVbwCgObiuyX9uV0LSAMY707IEgMkExJqXmsB4OWKxvB7epRB9G/3+F+pcrQpODlDuL9oDUAsa65zEpYF0Wbn7Oh7nrMQncyUPpyr9WUlALl0gRWytOA23S+y5joa4M34KFpawFgoqTu/2EEH4Xl1zo+0fy73fEto+nfkUY+meuyGZ1nUx/+DljP7ZqxHBFSlLODmtuTMdswUbHbXbWneW51D7Jm7xB8nSdiA2JQNK5+Sg5x8aNfgvFTt/m2w2+qpsyFa5Wjeu6fZmXSl840CA07aXbk9vN4I81WmJyblD/ZA=="
   686  	PrivateKey   = `
   687  -----BEGIN RSA PRIVATE KEY-----
   688  MIIEowIBAAKCAQEAgUElV5mwqkloIrM8ZNZ72gSCcnSJt7+/Usa5G+D15YQUAdf9
   689  c1zEekTfHgDP+04nw/uFNFaE5v1RbHaPxhZYVg5ZErNCa/hzn+x10xzcepeS3KPV
   690  Xcxae4MR0BEegvqZqJzN9loXsNL/c3H/B+2Gle3hTxjlWFb3F5qLgR+4Mf4ruhER
   691  1v6eHQa/nchi03MBpT4UeJ7MrL92hTJYLdpSyCqmr8yjxkKJDVC2uRrr+sTSxfh7
   692  r6v24u/vp/QTmBIAlNPgadVAZw17iNNb7vjV7Gwl/5gHXonCUKURaV++dBNLrHIZ
   693  pqcAM8wHRph8mD1EfL9hsz77pHewxolBATV+7QIDAQABAoIBAC1rK+kFW3vrAYm3
   694  +8/fQnQQw5nec4o6+crng6JVQXLeH32qXShNf8kLLG/Jj0vaYcTPPDZw9JCKkTMQ
   695  0mKj9XR/5DLbBMsV6eNXXuvJJ3x4iKW5eD9WkLD4FKlNarBRyO7j8sfPTqXW7uat
   696  NxWdFH7YsSRvNh/9pyQHLWA5OituidMrYbc3EUx8B1GPNyJ9W8Q8znNYLfwYOjU4
   697  Wv1SLE6qGQQH9Q0WzA2WUf8jklCYyMYTIywAjGb8kbAJlKhmj2t2Igjmqtwt1PYc
   698  pGlqbtQBDUiWXt5S4YX/1maIQ/49yeNUajjpbJiH3DbhJbHwFTzP3pZ9P9GHOzlG
   699  kYR+wSECgYEAw/Xida8kSv8n86V3qSY/I+fYQ5V+jDtXIE+JhRnS8xzbOzz3v0WS
   700  Oo5H+o4nJx5eL3Ghb3Gcm0Jn46dHrxinHbm+3RjXv/X6tlbxIYjRSQfHOTSMCTvd
   701  qcliF5vC6RCLXuc7R+IWR1Ky6eDEZGtrvt3DyeYABsp9fRUFR/6NluUCgYEAqNsw
   702  1aSl7WJa27F0DoJdlU9LWerpXcazlJcIdOz/S9QDmSK3RDQTdqfTxRmrxiYI9LEs
   703  mkOkvzlnnOBMpnZ3ZOU5qIRfprecRIi37KDAOHWGnlC0EWGgl46YLb7/jXiWf0AG
   704  Y+DfJJNd9i6TbIDWu8254/erAS6bKMhW/3q7f2kCgYAZ7Id/BiKJAWRpqTRBXlvw
   705  BhXoKvjI2HjYP21z/EyZ+PFPzur/lNaZhIUlMnUfibbwE9pFggQzzf8scM7c7Sf+
   706  mLoVSdoQ/Rujz7CqvQzi2nKSsM7t0curUIb3lJWee5/UeEaxZcmIufoNUrzohAWH
   707  BJOIPDM4ssUTLRq7wYM9uQKBgHCBau5OP8gE6mjKuXsZXWUoahpFLKwwwmJUp2vQ
   708  pOFPJ/6WZOlqkTVT6QPAcPUbTohKrF80hsZqZyDdSfT3peFx4ZLocBrS56m6NmHR
   709  UYHMvJ8rQm76T1fryHVidz85g3zRmfBeWg8yqT5oFg4LYgfLsPm1gRjOhs8LfPvI
   710  OLlRAoGBAIZ5Uv4Z3s8O7WKXXUe/lq6j7vfiVkR1NW/Z/WLKXZpnmvJ7FgxN4e56
   711  RXT7GwNQHIY8eDjDnsHxzrxd+raOxOZeKcMHj3XyjCX3NHfTscnsBPAGYpY/Wxzh
   712  T8UYnFu6RzkixElTf2rseEav7rkdKkI3LAeIZy7B0HulKKsmqVQ7
   713  -----END RSA PRIVATE KEY-----
   714  `
   715  	OpenSSHPrivateKey = `
   716  -----BEGIN OPENSSH PRIVATE KEY-----
   717  b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
   718  NhAAAAAwEAAQAAAQEAgUElV5mwqkloIrM8ZNZ72gSCcnSJt7+/Usa5G+D15YQUAdf9c1zE
   719  ekTfHgDP+04nw/uFNFaE5v1RbHaPxhZYVg5ZErNCa/hzn+x10xzcepeS3KPVXcxae4MR0B
   720  EegvqZqJzN9loXsNL/c3H/B+2Gle3hTxjlWFb3F5qLgR+4Mf4ruhER1v6eHQa/nchi03MB
   721  pT4UeJ7MrL92hTJYLdpSyCqmr8yjxkKJDVC2uRrr+sTSxfh7r6v24u/vp/QTmBIAlNPgad
   722  VAZw17iNNb7vjV7Gwl/5gHXonCUKURaV++dBNLrHIZpqcAM8wHRph8mD1EfL9hsz77pHew
   723  xolBATV+7QAAA7jbhEFk24RBZAAAAAdzc2gtcnNhAAABAQCBQSVXmbCqSWgiszxk1nvaBI
   724  JydIm3v79Sxrkb4PXlhBQB1/1zXMR6RN8eAM/7TifD+4U0VoTm/VFsdo/GFlhWDlkSs0Jr
   725  +HOf7HXTHNx6l5Lco9VdzFp7gxHQER6C+pmonM32Whew0v9zcf8H7YaV7eFPGOVYVvcXmo
   726  uBH7gx/iu6ERHW/p4dBr+dyGLTcwGlPhR4nsysv3aFMlgt2lLIKqavzKPGQokNULa5Guv6
   727  xNLF+Huvq/bi7++n9BOYEgCU0+Bp1UBnDXuI01vu+NXsbCX/mAdeicJQpRFpX750E0usch
   728  mmpwAzzAdGmHyYPUR8v2GzPvukd7DGiUEBNX7tAAAAAwEAAQAAAQAtayvpBVt76wGJt/vP
   729  30J0EMOZ3nOKOvnK54OiVUFy3h99ql0oTX/JCyxvyY9L2mHEzzw2cPSQipEzENJio/V0f+
   730  Qy2wTLFenjV17rySd8eIiluXg/VpCw+BSpTWqwUcju4/LHz06l1u7mrTcVnRR+2LEkbzYf
   731  /ackBy1gOTorbonTK2G3NxFMfAdRjzcifVvEPM5zWC38GDo1OFr9UixOqhkEB/UNFswNll
   732  H/I5JQmMjGEyMsAIxm/JGwCZSoZo9rdiII5qrcLdT2HKRpam7UAQ1Ill7eUuGF/9ZmiEP+
   733  PcnjVGo46WyYh9w24SWx8BU8z96WfT/Rhzs5RpGEfsEhAAAAgQCGeVL+Gd7PDu1il11Hv5
   734  auo+734lZEdTVv2f1iyl2aZ5ryexYMTeHuekV0+xsDUByGPHg4w57B8c68Xfq2jsTmXinD
   735  B4918owl9zR307HJ7ATwBmKWP1sc4U/FGJxbukc5IsRJU39q7HhGr+65HSpCNywHiGcuwd
   736  B7pSirJqlUOwAAAIEAw/Xida8kSv8n86V3qSY/I+fYQ5V+jDtXIE+JhRnS8xzbOzz3v0WS
   737  Oo5H+o4nJx5eL3Ghb3Gcm0Jn46dHrxinHbm+3RjXv/X6tlbxIYjRSQfHOTSMCTvdqcliF5
   738  vC6RCLXuc7R+IWR1Ky6eDEZGtrvt3DyeYABsp9fRUFR/6NluUAAACBAKjbMNWkpe1iWtux
   739  dA6CXZVPS1nq6V3Gs5SXCHTs/0vUA5kit0Q0E3an08UZq8YmCPSxLJpDpL85Z5zgTKZ2d2
   740  TlOaiEX6a3nESIt+ygwDh1hp5QtBFhoJeOmC2+/414ln9ABmPg3ySTXfYuk2yA1rvNueP3
   741  qwEumyjIVv96u39pAAAAAAEC
   742  -----END OPENSSH PRIVATE KEY-----
   743  `
   744  	WrongPrivateKey = `
   745  -----BEGIN RSA PRIVATE KEY-----
   746  MIIEowIBAAKCAQEAlrCgnEVgmNKCq7KPc+zUU5IrxPu1ClMNJS7RTsTPEkbwe5SB
   747  p+6V6WtCbD/X/lDRRGbOENChh1Phulb7lViqgrdpHydgsrKoS5ah3DfSIxLFLE00
   748  9Yo4TCYwgw6+s59j16ZAFVinaQ9l6Kmrb2ll136hMrz8QKh+qw+onOLd38WFgm+W
   749  ZtUqSXf2LANzfzzy4OWFNyFqKaCAolSkPdTS9Nz+svtScvp002DQp8OdP1AgPO+l
   750  o5N3M38Fftapwg0pCtJ5Zq0NRWIXEonXiTEMA6zy3gEZVOmDxoIFUWnmrqlMJLFy
   751  5S6LDrHSdqJhCxDK6WRZj43X9j8spktk3eGhMwIDAQABAoIBAAem8ID/BOi9x+Tw
   752  LFi2rhGQWqimH4tmrEQ3HGnjlKBY+d1MrUjZ1MMFr1nP5CgF8pqGnfA8p/c3Sz8r
   753  K5tp5T6+EZiDZ2WrrOApxg5ox0MAsQKO6SGO40z6o3wEQ6rbbTaGOrraxaWQIpyu
   754  AQanU4Sd6ZGqByVBaS1GnklZO+shCHqw73b7g1cpLEmFzcYnKHYHlUUIsstMe8E1
   755  BaCY0CH7JbWBjcbiTnBVwIRZuu+EjGiQuhTilYL2OWqoMVg1WU0L2IFpR8lkf/2W
   756  SBx5J6xhwbBGASOpM+qidiN580GdPzGhWYSqKGroHEzBm6xPSmV1tadNA26WFG4p
   757  pthLiAECgYEA5BsPRpNYJAQLu5B0N7mj9eEp0HABVEgL/MpwiImjaKdAwp78HM64
   758  IuPvJxs7r+xESiIz4JyjR8zrQjYOCKJsARYkmNlEuAz0SkHabCw1BdEBwUhjUGVB
   759  efoERK6GxfAoNqmSDwsOvHFOtsmDIlbHmg7G2rUxNVpeou415BSB0B8CgYEAqR4J
   760  YHKk2Ibr9rU+rBU33TcdTGw0aAkFNAVeqM9j0haWuFXmV3RArgoy09lH+2Ha6z/g
   761  fTX2xSDAWV7QUlLOlBRIhurPAo2jO2yCrGHPZcWiugstrR2hTTInigaSnCmK3i7F
   762  6sYmL3S7K01IcVNxSlWvGijtClT92Cl2WUCTfG0CgYAiEjyk4QtQTd5mxLvnOu5X
   763  oqs5PBGmwiAwQRiv/EcRMbJFn7Oupd3xMDSflbzDmTnWDOfMy/jDl8MoH6TW+1PA
   764  kcsjnYhbKWwvz0hN0giVdtOZSDO1ZXpzOrn6fEsbM7T9/TQY1SD9WrtUKCNTNL0Z
   765  sM1ZC6lu+7GZCpW4HKwLJwKBgQCRT0yxQXBg1/UxwuO5ynV4rx2Oh76z0WRWIXMH
   766  S0MyxdP1SWGkrS/SGtM3cg/GcHtA/V6vV0nUcWK0p6IJyjrTw2XZ/zGluPuTWJYi
   767  9dvVT26Vunshrz7kbH7KuwEICy3V4IyQQHeY+QzFlR70uMS0IVFWAepCoWqHbIDT
   768  CYhwNQKBgGPcLXmjpGtkZvggl0aZr9LsvCTckllSCFSI861kivL/rijdNoCHGxZv
   769  dfDkLTLcz9Gk41rD9Gxn/3sqodnTAc3Z2PxFnzg1Q/u3+x6YAgBwI/g/jE2xutGW
   770  H7CurtMwALQ/n/6LUKFmjRZjqbKX9SO2QSaC3grd6sY9Tu+bZjLe
   771  -----END RSA PRIVATE KEY-----
   772  `
   773  	BadPrivateKey = `
   774  -----BEGIN RSA PRIVATE KEY-----
   775  MIIEowIBAAKCAQEAgUElV5mwqkloIrM8ZNZ72gSCcnSJt7+/Usa5G+D15YQUAdf9
   776  c1zEekTfHgDP+04nw/uFNFaE5v1RbHaPxhZYVg5ZErNCa/hzn+x10xzcepeS3KPV
   777  Xcxae4MR0BEegvqZqJzN9loXsNL/c3H/B+2Gle3hTxjlWFb3F5qLgR+4Mf4ruhER
   778  1v6eHQa/nchi03MBpT4UeJ7MrL92hTJYLdpSyCqmr8yjxkKJDVC2uRrr+sTSxfh7
   779  r6v24u/vp/QTmBIAlNPgadVAZw17iNNb7vjV7Gwl/5gHXonCUKURaV++dBNLrHIZ
   780  pqcAM8wHRph8mD1EfL9hsz77pHewxolBATV+7QIDAQABAoIBAC1rK+kFW3vrAYm3
   781  +8/fQnQQw5nec4o6+crng6JVQXLeH32qXShNf8kLLG/Jj0vaYcTPPDZw9JCKkTMQ
   782  0mKj9XR/5DLbBMsV6eNXXuvJJ3x4iKW5eD9WkLD4FKlNarBRyO7j8sfPTqXW7uat
   783  NxWdFH7YsSRvNh/9pyQHLWA5OituidMrYbc3EUx8B1GPNyJ9W8Q8znNYLfwYOjU4
   784  Wv1SLE6qGQQH9Q0WzA2WUf8jklCYyMYTIywAjGb8kbAJlKhmj2t2Igjmqtwt1PYc
   785  pGlqbtQBDUiWXt5S4YX/1maIQ/49yeNUajjpbJiH3DbhJbHwFTzP3pZ9P9GHOzlG
   786  kYR+wSECgYEAw/Xida8kSv8n86V3qSY/I+fYQ5V+jDtXIE+JhRnS8xzbOzz3v0WS
   787  Oo5H+o4nJx5eL3Ghb3Gcm0Jn46dHrxinHbm+3RjXv/X6tlbxIYjRSQfHOTSMCTvd
   788  qcliF5vC6RCLXuc7R+IWR1Ky6eDEZGtrvt3DyeYABsp9fRUFR/6NluUCgYEAqNsw
   789  1aSl7WJa27F0DoJdlU9LWerpXcazlJcIdOz/S9QDmSK3RDQTdqfTxRmrxiYI9LEs
   790  mkOkvzlnnOBMpnZ3ZOU5qIRfprecRIi37KDAOHWGnlC0EWGgl46YLb7/jXiWf0AG
   791  BhXoKvjI2HjYP21z/EyZ+PFPzur/lNaZhIUlMnUfibbwE9pFggQzzf8scM7c7Sf+
   792  mLoVSdoQ/Rujz7CqvQzi2nKSsM7t0curUIb3lJWee5/UeEaxZcmIufoNUrzohAWH
   793  BJOIPDM4ssUTLRq7wYM9uQKBgHCBau5OP8gE6mjKuXsZXWUoahpFLKwwwmJUp2vQ
   794  pOFPJ/6WZOlqkTVT6QPAcPUbTohKrF80hsZqZyDdSfT3peFx4ZLocBrS56m6NmHR
   795  UYHMvJ8rQm76T1fryHVidz85g3zRmfBeWg8yqT5oFg4LYgfLsPm1gRjOhs8LfPvI
   796  OLlRAoGBAIZ5Uv4Z3s8O7WKXXUe/lq6j7vfiVkR1NW/Z/WLKXZpnmvJ7FgxN4e56
   797  RXT7GwNQHIY8eDjDnsHxzrxd+raOxOZeKcMHj3XyjCX3NHfTscnsBPAGYpY/Wxzh
   798  T8UYnFu6RzkixElTf2rseEav7rkdKkI3LAeIZy7B0HulKKsmqVQ7
   799  -----END RSA PRIVATE KEY-----
   800  `
   801  )