...

Source file src/encoding/pem/pem_test.go

Documentation: encoding/pem

     1  // Copyright 2009 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 pem
     6  
     7  import (
     8  	"bytes"
     9  	"io"
    10  	"reflect"
    11  	"strings"
    12  	"testing"
    13  	"testing/quick"
    14  )
    15  
    16  type GetLineTest struct {
    17  	in, out1, out2 string
    18  }
    19  
    20  var getLineTests = []GetLineTest{
    21  	{"abc", "abc", ""},
    22  	{"abc\r", "abc\r", ""},
    23  	{"abc\n", "abc", ""},
    24  	{"abc\r\n", "abc", ""},
    25  	{"abc\nd", "abc", "d"},
    26  	{"abc\r\nd", "abc", "d"},
    27  	{"\nabc", "", "abc"},
    28  	{"\r\nabc", "", "abc"},
    29  	{"abc\t \nd", "abc", "d"},
    30  	{"\t abc\nd", "\t abc", "d"},
    31  	{"abc\n\t d", "abc", "\t d"},
    32  	{"abc\nd\t ", "abc", "d\t "},
    33  }
    34  
    35  func TestGetLine(t *testing.T) {
    36  	for i, test := range getLineTests {
    37  		x, y, _ := getLine([]byte(test.in))
    38  		if string(x) != test.out1 || string(y) != test.out2 {
    39  			t.Errorf("#%d got:%+v,%+v want:%s,%s", i, x, y, test.out1, test.out2)
    40  		}
    41  	}
    42  }
    43  
    44  func TestDecode(t *testing.T) {
    45  	result, remainder := Decode([]byte(pemData))
    46  	if !reflect.DeepEqual(result, certificate) {
    47  		t.Errorf("#0 got:%#v want:%#v", result, certificate)
    48  	}
    49  
    50  	result, remainder = Decode(remainder)
    51  	if !reflect.DeepEqual(result, privateKey) {
    52  		t.Errorf("#1 got:%#v want:%#v", result, privateKey)
    53  	}
    54  
    55  	isEmpty := func(block *Block) bool {
    56  		return block != nil && block.Type == "EMPTY" && len(block.Headers) == 0 && len(block.Bytes) == 0
    57  	}
    58  	result, remainder = Decode(remainder)
    59  	if !isEmpty(result) {
    60  		t.Errorf("#2 should be empty but got:%#v", result)
    61  	}
    62  	result, remainder = Decode(remainder)
    63  	if !isEmpty(result) {
    64  		t.Errorf("#3 should be empty but got:%#v", result)
    65  	}
    66  	result, remainder = Decode(remainder)
    67  	if !isEmpty(result) {
    68  		t.Errorf("#4 should be empty but got:%#v", result)
    69  	}
    70  
    71  	result, remainder = Decode(remainder)
    72  	if result == nil || result.Type != "VALID HEADERS" || len(result.Headers) != 1 {
    73  		t.Errorf("#5 expected single header block but got :%v", result)
    74  	}
    75  
    76  	if len(remainder) != 0 {
    77  		t.Errorf("expected nothing remaining of pemData, but found %s", string(remainder))
    78  	}
    79  
    80  	result, _ = Decode([]byte(pemPrivateKey2))
    81  	if !reflect.DeepEqual(result, privateKey2) {
    82  		t.Errorf("#2 got:%#v want:%#v", result, privateKey2)
    83  	}
    84  }
    85  
    86  const pemTooFewEndingDashes = `
    87  -----BEGIN FOO-----
    88  dGVzdA==
    89  -----END FOO----`
    90  
    91  const pemTooManyEndingDashes = `
    92  -----BEGIN FOO-----
    93  dGVzdA==
    94  -----END FOO------`
    95  
    96  const pemTrailingNonWhitespace = `
    97  -----BEGIN FOO-----
    98  dGVzdA==
    99  -----END FOO----- .`
   100  
   101  const pemWrongEndingType = `
   102  -----BEGIN FOO-----
   103  dGVzdA==
   104  -----END BAR-----`
   105  
   106  const pemMissingEndingSpace = `
   107  -----BEGIN FOO-----
   108  dGVzdA==
   109  -----ENDBAR-----`
   110  
   111  const pemMissingEndLine = `
   112  -----BEGIN FOO-----
   113  Header: 1`
   114  
   115  var pemRepeatingBegin = strings.Repeat("-----BEGIN \n", 10)
   116  
   117  var badPEMTests = []struct {
   118  	name  string
   119  	input string
   120  }{
   121  	{
   122  		"too few trailing dashes",
   123  		pemTooFewEndingDashes,
   124  	},
   125  	{
   126  		"too many trailing dashes",
   127  		pemTooManyEndingDashes,
   128  	},
   129  	{
   130  		"trailing non-whitespace",
   131  		pemTrailingNonWhitespace,
   132  	},
   133  	{
   134  		"incorrect ending type",
   135  		pemWrongEndingType,
   136  	},
   137  	{
   138  		"missing ending space",
   139  		pemMissingEndingSpace,
   140  	},
   141  	{
   142  		"repeating begin",
   143  		pemRepeatingBegin,
   144  	},
   145  	{
   146  		"missing end line",
   147  		pemMissingEndLine,
   148  	},
   149  }
   150  
   151  func TestBadDecode(t *testing.T) {
   152  	for _, test := range badPEMTests {
   153  		result, rest := Decode([]byte(test.input))
   154  		if result != nil {
   155  			t.Errorf("unexpected success while parsing %q", test.name)
   156  		}
   157  		if string(rest) != test.input {
   158  			t.Errorf("unexpected rest: %q; want = %q", rest, test.input)
   159  		}
   160  	}
   161  }
   162  
   163  func TestCVE202224675(t *testing.T) {
   164  	// Prior to CVE-2022-24675, this input would cause a stack overflow.
   165  	input := []byte(strings.Repeat("-----BEGIN \n", 10000000))
   166  	result, rest := Decode(input)
   167  	if result != nil || !bytes.Equal(rest, input) {
   168  		t.Errorf("Encode of %#v decoded as %#v", input, rest)
   169  	}
   170  }
   171  
   172  func TestEncode(t *testing.T) {
   173  	r := EncodeToMemory(privateKey2)
   174  	if string(r) != pemPrivateKey2 {
   175  		t.Errorf("got:%s want:%s", r, pemPrivateKey2)
   176  	}
   177  }
   178  
   179  type lineBreakerTest struct {
   180  	in, out string
   181  }
   182  
   183  const sixtyFourCharString = "0123456789012345678901234567890123456789012345678901234567890123"
   184  
   185  var lineBreakerTests = []lineBreakerTest{
   186  	{"", ""},
   187  	{"a", "a\n"},
   188  	{"ab", "ab\n"},
   189  	{sixtyFourCharString, sixtyFourCharString + "\n"},
   190  	{sixtyFourCharString + "X", sixtyFourCharString + "\nX\n"},
   191  	{sixtyFourCharString + sixtyFourCharString, sixtyFourCharString + "\n" + sixtyFourCharString + "\n"},
   192  }
   193  
   194  func TestLineBreaker(t *testing.T) {
   195  	for i, test := range lineBreakerTests {
   196  		buf := new(strings.Builder)
   197  		var breaker lineBreaker
   198  		breaker.out = buf
   199  		_, err := breaker.Write([]byte(test.in))
   200  		if err != nil {
   201  			t.Errorf("#%d: error from Write: %s", i, err)
   202  			continue
   203  		}
   204  		err = breaker.Close()
   205  		if err != nil {
   206  			t.Errorf("#%d: error from Close: %s", i, err)
   207  			continue
   208  		}
   209  
   210  		if got := buf.String(); got != test.out {
   211  			t.Errorf("#%d: got:%s want:%s", i, got, test.out)
   212  		}
   213  	}
   214  
   215  	for i, test := range lineBreakerTests {
   216  		buf := new(strings.Builder)
   217  		var breaker lineBreaker
   218  		breaker.out = buf
   219  
   220  		for i := 0; i < len(test.in); i++ {
   221  			_, err := breaker.Write([]byte(test.in[i : i+1]))
   222  			if err != nil {
   223  				t.Errorf("#%d: error from Write (byte by byte): %s", i, err)
   224  				continue
   225  			}
   226  		}
   227  		err := breaker.Close()
   228  		if err != nil {
   229  			t.Errorf("#%d: error from Close (byte by byte): %s", i, err)
   230  			continue
   231  		}
   232  
   233  		if got := buf.String(); got != test.out {
   234  			t.Errorf("#%d: (byte by byte) got:%s want:%s", i, got, test.out)
   235  		}
   236  	}
   237  }
   238  
   239  func TestFuzz(t *testing.T) {
   240  	// PEM is a text-based format. Assume header fields with leading/trailing spaces
   241  	// or embedded newlines will not round trip correctly and don't need to be tested.
   242  	isBad := func(s string) bool {
   243  		return strings.ContainsAny(s, "\r\n") || strings.TrimSpace(s) != s
   244  	}
   245  
   246  	testRoundtrip := func(block Block) bool {
   247  		// Reject bad Type
   248  		// Type with colons will proceed as key/val pair and cause an error.
   249  		if isBad(block.Type) || strings.Contains(block.Type, ":") {
   250  			return true
   251  		}
   252  		for key, val := range block.Headers {
   253  			// Reject bad key/val.
   254  			// Also, keys with colons cannot be encoded, because : is the key: val separator.
   255  			if isBad(key) || isBad(val) || strings.Contains(key, ":") {
   256  				return true
   257  			}
   258  		}
   259  
   260  		var buf bytes.Buffer
   261  		if err := Encode(&buf, &block); err != nil {
   262  			t.Errorf("Encode of %#v resulted in error: %s", &block, err)
   263  			return false
   264  		}
   265  		decoded, rest := Decode(buf.Bytes())
   266  		if block.Headers == nil {
   267  			// Encoder supports nil Headers but decoder returns initialized.
   268  			block.Headers = make(map[string]string)
   269  		}
   270  		if block.Bytes == nil {
   271  			// Encoder supports nil Bytes but decoder returns initialized.
   272  			block.Bytes = make([]byte, 0)
   273  		}
   274  		if !reflect.DeepEqual(decoded, &block) {
   275  			t.Errorf("Encode of %#v decoded as %#v", &block, decoded)
   276  			return false
   277  		}
   278  		if len(rest) != 0 {
   279  			t.Errorf("Encode of %#v decoded correctly, but with %x left over", block, rest)
   280  			return false
   281  		}
   282  		return true
   283  	}
   284  
   285  	// Explicitly test the empty block.
   286  	if !testRoundtrip(Block{
   287  		Type:    "EMPTY",
   288  		Headers: make(map[string]string),
   289  		Bytes:   []byte{},
   290  	}) {
   291  		return
   292  	}
   293  
   294  	quick.Check(testRoundtrip, nil)
   295  }
   296  
   297  func BenchmarkEncode(b *testing.B) {
   298  	data := &Block{Bytes: make([]byte, 65536)}
   299  	b.SetBytes(int64(len(data.Bytes)))
   300  	for i := 0; i < b.N; i++ {
   301  		Encode(io.Discard, data)
   302  	}
   303  }
   304  
   305  func BenchmarkDecode(b *testing.B) {
   306  	block := &Block{Bytes: make([]byte, 65536)}
   307  	data := EncodeToMemory(block)
   308  	b.SetBytes(int64(len(data)))
   309  	b.ResetTimer()
   310  	for i := 0; i < b.N; i++ {
   311  		Decode(data)
   312  	}
   313  }
   314  
   315  var pemData = testingKey(`verify return:0
   316  -----BEGIN CERTIFICATE-----
   317  sdlfkjskldfj
   318    -----BEGIN CERTIFICATE-----
   319  ---
   320  Certificate chain
   321   0 s:/C=AU/ST=Somewhere/L=Someplace/O=Foo Bar/CN=foo.example.com
   322     i:/C=ZA/O=CA Inc./CN=CA Inc
   323  -----BEGIN CERTIFICATE-----
   324  testing
   325  -----BEGIN CERTIFICATE-----
   326  -----BEGIN CERTIFICATE-----
   327  MIID6TCCA1ICAQEwDQYJKoZIhvcNAQEFBQAwgYsxCzAJBgNVBAYTAlVTMRMwEQYD
   328  VQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQK
   329  EwtHb29nbGUgSW5jLjEMMAoGA1UECxMDRW5nMQwwCgYDVQQDEwNhZ2wxHTAbBgkq
   330  hkiG9w0BCQEWDmFnbEBnb29nbGUuY29tMB4XDTA5MDkwOTIyMDU0M1oXDTEwMDkw
   331  OTIyMDU0M1owajELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAf
   332  BgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEjMCEGA1UEAxMaZXVyb3Bh
   333  LnNmby5jb3JwLmdvb2dsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
   334  AoICAQC6pgYt7/EibBDumASF+S0qvqdL/f+nouJw2T1Qc8GmXF/iiUcrsgzh/Fd8
   335  pDhz/T96Qg9IyR4ztuc2MXrmPra+zAuSf5bevFReSqvpIt8Duv0HbDbcqs/XKPfB
   336  uMDe+of7a9GCywvAZ4ZUJcp0thqD9fKTTjUWOBzHY1uNE4RitrhmJCrbBGXbJ249
   337  bvgmb7jgdInH2PU7PT55hujvOoIsQW2osXBFRur4pF1wmVh4W4lTLD6pjfIMUcML
   338  ICHEXEN73PDic8KS3EtNYCwoIld+tpIBjE1QOb1KOyuJBNW6Esw9ALZn7stWdYcE
   339  qAwvv20egN2tEXqj7Q4/1ccyPZc3PQgC3FJ8Be2mtllM+80qf4dAaQ/fWvCtOrQ5
   340  pnfe9juQvCo8Y0VGlFcrSys/MzSg9LJ/24jZVgzQved/Qupsp89wVidwIzjt+WdS
   341  fyWfH0/v1aQLvu5cMYuW//C0W2nlYziL5blETntM8My2ybNARy3ICHxCBv2RNtPI
   342  WQVm+E9/W5rwh2IJR4DHn2LHwUVmT/hHNTdBLl5Uhwr4Wc7JhE7AVqb14pVNz1lr
   343  5jxsp//ncIwftb7mZQ3DF03Yna+jJhpzx8CQoeLT6aQCHyzmH68MrHHT4MALPyUs
   344  Pomjn71GNTtDeWAXibjCgdL6iHACCF6Htbl0zGlG0OAK+bdn0QIDAQABMA0GCSqG
   345  SIb3DQEBBQUAA4GBAOKnQDtqBV24vVqvesL5dnmyFpFPXBn3WdFfwD6DzEb21UVG
   346  5krmJiu+ViipORJPGMkgoL6BjU21XI95VQbun5P8vvg8Z+FnFsvRFY3e1CCzAVQY
   347  ZsUkLw2I7zI/dNlWdB8Xp7v+3w9sX5N3J/WuJ1KOO5m26kRlHQo7EzT3974g
   348  -----END CERTIFICATE-----
   349   1 s:/C=ZA/O=Ca Inc./CN=CA Inc
   350  
   351  -----BEGIN RSA TESTING KEY-----
   352  Proc-Type: 4,ENCRYPTED
   353  DEK-Info: DES-EDE3-CBC,80C7C7A09690757A
   354  
   355  eQp5ZkH6CyHBz7BZfUPxyLCCmftsBJ7HlqGb8Ld21cSwnzWZ4/SIlhyrUtsfw7VR
   356  2TTwA+odo9ex7GdxOTaH8oZFumIRoiEjHsk8U7Bhntp+ekkPP79xunnN7hb7hkhr
   357  yGDQZgA7s2cQHQ71v3gwT2BACAft26jCjbM1wgNzBnJ8M0Rzn68YWqaPtdBu8qb/
   358  zVR5JB1mnqvTSbFsfF5yMc6o2WQ9jJCl6KypnMl+BpL+dlvdjYVK4l9lYsB1Hs3d
   359  +zDBbWxos818zzhS8/y6eIfiSG27cqrbhURbmgiSfDXjncK4m/pLcQ7mmBL6mFOr
   360  3Pj4jepzgOiFRL6MKE//h62fZvI1ErYr8VunHEykgKNhChDvb1RO6LEfqKBu+Ivw
   361  TB6fBhW3TCLMnVPYVoYwA+fHNTmZZm8BEonlIMfI+KktjWUg4Oia+NI6vKcPpFox
   362  hSnlGgCtvfEaq5/H4kHJp95eOpnFsLviw2seHNkz/LxJMRP1X428+DpYW/QD/0JU
   363  tJSuC/q9FUHL6RI3u/Asrv8pCb4+D7i1jW/AMIdJTtycOGsbPxQA7yHMWujHmeb1
   364  BTiHcL3s3KrJu1vDVrshvxfnz71KTeNnZH8UbOqT5i7fPGyXtY1XJddcbI/Q6tXf
   365  wHFsZc20TzSdsVLBtwksUacpbDogcEVMctnNrB8FIrB3vZEv9Q0Z1VeY7nmTpF+6
   366  a+z2P7acL7j6A6Pr3+q8P9CPiPC7zFonVzuVPyB8GchGR2hytyiOVpuD9+k8hcuw
   367  ZWAaUoVtWIQ52aKS0p19G99hhb+IVANC4akkdHV4SP8i7MVNZhfUmg==
   368  -----END RSA TESTING KEY-----
   369  
   370  
   371  -----BEGIN EMPTY-----
   372  -----END EMPTY-----
   373  
   374  -----BEGIN EMPTY-----
   375  
   376  -----END EMPTY-----
   377  
   378  -----BEGIN EMPTY-----
   379  
   380  
   381  -----END EMPTY-----
   382  
   383  # This shouldn't be recognised because of the missing newline after the
   384  headers.
   385  -----BEGIN INVALID HEADERS-----
   386  Header: 1
   387  -----END INVALID HEADERS-----
   388  
   389  # This should be valid, however.
   390  -----BEGIN VALID HEADERS-----
   391  Header: 1
   392  
   393  -----END VALID HEADERS-----`)
   394  
   395  var certificate = &Block{Type: "CERTIFICATE",
   396  	Headers: map[string]string{},
   397  	Bytes: []uint8{0x30, 0x82, 0x3, 0xe9, 0x30, 0x82, 0x3, 0x52, 0x2, 0x1,
   398  		0x1, 0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd,
   399  		0x1, 0x1, 0x5, 0x5, 0x0, 0x30, 0x81, 0x8b, 0x31, 0xb, 0x30,
   400  		0x9, 0x6, 0x3, 0x55, 0x4, 0x6, 0x13, 0x2, 0x55, 0x53, 0x31,
   401  		0x13, 0x30, 0x11, 0x6, 0x3, 0x55, 0x4, 0x8, 0x13, 0xa, 0x43,
   402  		0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31,
   403  		0x16, 0x30, 0x14, 0x6, 0x3, 0x55, 0x4, 0x7, 0x13, 0xd, 0x53,
   404  		0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73,
   405  		0x63, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x6, 0x3, 0x55, 0x4, 0xa,
   406  		0x13, 0xb, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49,
   407  		0x6e, 0x63, 0x2e, 0x31, 0xc, 0x30, 0xa, 0x6, 0x3, 0x55, 0x4,
   408  		0xb, 0x13, 0x3, 0x45, 0x6e, 0x67, 0x31, 0xc, 0x30, 0xa, 0x6,
   409  		0x3, 0x55, 0x4, 0x3, 0x13, 0x3, 0x61, 0x67, 0x6c, 0x31, 0x1d,
   410  		0x30, 0x1b, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1,
   411  		0x9, 0x1, 0x16, 0xe, 0x61, 0x67, 0x6c, 0x40, 0x67, 0x6f, 0x6f,
   412  		0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17,
   413  		0xd, 0x30, 0x39, 0x30, 0x39, 0x30, 0x39, 0x32, 0x32, 0x30,
   414  		0x35, 0x34, 0x33, 0x5a, 0x17, 0xd, 0x31, 0x30, 0x30, 0x39,
   415  		0x30, 0x39, 0x32, 0x32, 0x30, 0x35, 0x34, 0x33, 0x5a, 0x30,
   416  		0x6a, 0x31, 0xb, 0x30, 0x9, 0x6, 0x3, 0x55, 0x4, 0x6, 0x13,
   417  		0x2, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x6, 0x3, 0x55, 0x4,
   418  		0x8, 0x13, 0xa, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61,
   419  		0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x6, 0x3, 0x55, 0x4, 0xa,
   420  		0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
   421  		0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
   422  		0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x23, 0x30, 0x21,
   423  		0x6, 0x3, 0x55, 0x4, 0x3, 0x13, 0x1a, 0x65, 0x75, 0x72, 0x6f,
   424  		0x70, 0x61, 0x2e, 0x73, 0x66, 0x6f, 0x2e, 0x63, 0x6f, 0x72,
   425  		0x70, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63,
   426  		0x6f, 0x6d, 0x30, 0x82, 0x2, 0x22, 0x30, 0xd, 0x6, 0x9, 0x2a,
   427  		0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x1, 0x5, 0x0, 0x3,
   428  		0x82, 0x2, 0xf, 0x0, 0x30, 0x82, 0x2, 0xa, 0x2, 0x82, 0x2, 0x1,
   429  		0x0, 0xba, 0xa6, 0x6, 0x2d, 0xef, 0xf1, 0x22, 0x6c, 0x10, 0xee,
   430  		0x98, 0x4, 0x85, 0xf9, 0x2d, 0x2a, 0xbe, 0xa7, 0x4b, 0xfd,
   431  		0xff, 0xa7, 0xa2, 0xe2, 0x70, 0xd9, 0x3d, 0x50, 0x73, 0xc1,
   432  		0xa6, 0x5c, 0x5f, 0xe2, 0x89, 0x47, 0x2b, 0xb2, 0xc, 0xe1,
   433  		0xfc, 0x57, 0x7c, 0xa4, 0x38, 0x73, 0xfd, 0x3f, 0x7a, 0x42,
   434  		0xf, 0x48, 0xc9, 0x1e, 0x33, 0xb6, 0xe7, 0x36, 0x31, 0x7a,
   435  		0xe6, 0x3e, 0xb6, 0xbe, 0xcc, 0xb, 0x92, 0x7f, 0x96, 0xde,
   436  		0xbc, 0x54, 0x5e, 0x4a, 0xab, 0xe9, 0x22, 0xdf, 0x3, 0xba,
   437  		0xfd, 0x7, 0x6c, 0x36, 0xdc, 0xaa, 0xcf, 0xd7, 0x28, 0xf7,
   438  		0xc1, 0xb8, 0xc0, 0xde, 0xfa, 0x87, 0xfb, 0x6b, 0xd1, 0x82,
   439  		0xcb, 0xb, 0xc0, 0x67, 0x86, 0x54, 0x25, 0xca, 0x74, 0xb6,
   440  		0x1a, 0x83, 0xf5, 0xf2, 0x93, 0x4e, 0x35, 0x16, 0x38, 0x1c,
   441  		0xc7, 0x63, 0x5b, 0x8d, 0x13, 0x84, 0x62, 0xb6, 0xb8, 0x66,
   442  		0x24, 0x2a, 0xdb, 0x4, 0x65, 0xdb, 0x27, 0x6e, 0x3d, 0x6e,
   443  		0xf8, 0x26, 0x6f, 0xb8, 0xe0, 0x74, 0x89, 0xc7, 0xd8, 0xf5,
   444  		0x3b, 0x3d, 0x3e, 0x79, 0x86, 0xe8, 0xef, 0x3a, 0x82, 0x2c,
   445  		0x41, 0x6d, 0xa8, 0xb1, 0x70, 0x45, 0x46, 0xea, 0xf8, 0xa4,
   446  		0x5d, 0x70, 0x99, 0x58, 0x78, 0x5b, 0x89, 0x53, 0x2c, 0x3e,
   447  		0xa9, 0x8d, 0xf2, 0xc, 0x51, 0xc3, 0xb, 0x20, 0x21, 0xc4, 0x5c,
   448  		0x43, 0x7b, 0xdc, 0xf0, 0xe2, 0x73, 0xc2, 0x92, 0xdc, 0x4b,
   449  		0x4d, 0x60, 0x2c, 0x28, 0x22, 0x57, 0x7e, 0xb6, 0x92, 0x1,
   450  		0x8c, 0x4d, 0x50, 0x39, 0xbd, 0x4a, 0x3b, 0x2b, 0x89, 0x4,
   451  		0xd5, 0xba, 0x12, 0xcc, 0x3d, 0x0, 0xb6, 0x67, 0xee, 0xcb,
   452  		0x56, 0x75, 0x87, 0x4, 0xa8, 0xc, 0x2f, 0xbf, 0x6d, 0x1e, 0x80,
   453  		0xdd, 0xad, 0x11, 0x7a, 0xa3, 0xed, 0xe, 0x3f, 0xd5, 0xc7,
   454  		0x32, 0x3d, 0x97, 0x37, 0x3d, 0x8, 0x2, 0xdc, 0x52, 0x7c, 0x5,
   455  		0xed, 0xa6, 0xb6, 0x59, 0x4c, 0xfb, 0xcd, 0x2a, 0x7f, 0x87,
   456  		0x40, 0x69, 0xf, 0xdf, 0x5a, 0xf0, 0xad, 0x3a, 0xb4, 0x39,
   457  		0xa6, 0x77, 0xde, 0xf6, 0x3b, 0x90, 0xbc, 0x2a, 0x3c, 0x63,
   458  		0x45, 0x46, 0x94, 0x57, 0x2b, 0x4b, 0x2b, 0x3f, 0x33, 0x34,
   459  		0xa0, 0xf4, 0xb2, 0x7f, 0xdb, 0x88, 0xd9, 0x56, 0xc, 0xd0,
   460  		0xbd, 0xe7, 0x7f, 0x42, 0xea, 0x6c, 0xa7, 0xcf, 0x70, 0x56,
   461  		0x27, 0x70, 0x23, 0x38, 0xed, 0xf9, 0x67, 0x52, 0x7f, 0x25,
   462  		0x9f, 0x1f, 0x4f, 0xef, 0xd5, 0xa4, 0xb, 0xbe, 0xee, 0x5c,
   463  		0x31, 0x8b, 0x96, 0xff, 0xf0, 0xb4, 0x5b, 0x69, 0xe5, 0x63,
   464  		0x38, 0x8b, 0xe5, 0xb9, 0x44, 0x4e, 0x7b, 0x4c, 0xf0, 0xcc,
   465  		0xb6, 0xc9, 0xb3, 0x40, 0x47, 0x2d, 0xc8, 0x8, 0x7c, 0x42, 0x6,
   466  		0xfd, 0x91, 0x36, 0xd3, 0xc8, 0x59, 0x5, 0x66, 0xf8, 0x4f,
   467  		0x7f, 0x5b, 0x9a, 0xf0, 0x87, 0x62, 0x9, 0x47, 0x80, 0xc7,
   468  		0x9f, 0x62, 0xc7, 0xc1, 0x45, 0x66, 0x4f, 0xf8, 0x47, 0x35,
   469  		0x37, 0x41, 0x2e, 0x5e, 0x54, 0x87, 0xa, 0xf8, 0x59, 0xce,
   470  		0xc9, 0x84, 0x4e, 0xc0, 0x56, 0xa6, 0xf5, 0xe2, 0x95, 0x4d,
   471  		0xcf, 0x59, 0x6b, 0xe6, 0x3c, 0x6c, 0xa7, 0xff, 0xe7, 0x70,
   472  		0x8c, 0x1f, 0xb5, 0xbe, 0xe6, 0x65, 0xd, 0xc3, 0x17, 0x4d,
   473  		0xd8, 0x9d, 0xaf, 0xa3, 0x26, 0x1a, 0x73, 0xc7, 0xc0, 0x90,
   474  		0xa1, 0xe2, 0xd3, 0xe9, 0xa4, 0x2, 0x1f, 0x2c, 0xe6, 0x1f,
   475  		0xaf, 0xc, 0xac, 0x71, 0xd3, 0xe0, 0xc0, 0xb, 0x3f, 0x25, 0x2c,
   476  		0x3e, 0x89, 0xa3, 0x9f, 0xbd, 0x46, 0x35, 0x3b, 0x43, 0x79,
   477  		0x60, 0x17, 0x89, 0xb8, 0xc2, 0x81, 0xd2, 0xfa, 0x88, 0x70,
   478  		0x2, 0x8, 0x5e, 0x87, 0xb5, 0xb9, 0x74, 0xcc, 0x69, 0x46, 0xd0,
   479  		0xe0, 0xa, 0xf9, 0xb7, 0x67, 0xd1, 0x2, 0x3, 0x1, 0x0, 0x1,
   480  		0x30, 0xd, 0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1,
   481  		0x1, 0x5, 0x5, 0x0, 0x3, 0x81, 0x81, 0x0, 0xe2, 0xa7, 0x40,
   482  		0x3b, 0x6a, 0x5, 0x5d, 0xb8, 0xbd, 0x5a, 0xaf, 0x7a, 0xc2,
   483  		0xf9, 0x76, 0x79, 0xb2, 0x16, 0x91, 0x4f, 0x5c, 0x19, 0xf7,
   484  		0x59, 0xd1, 0x5f, 0xc0, 0x3e, 0x83, 0xcc, 0x46, 0xf6, 0xd5,
   485  		0x45, 0x46, 0xe6, 0x4a, 0xe6, 0x26, 0x2b, 0xbe, 0x56, 0x28,
   486  		0xa9, 0x39, 0x12, 0x4f, 0x18, 0xc9, 0x20, 0xa0, 0xbe, 0x81,
   487  		0x8d, 0x4d, 0xb5, 0x5c, 0x8f, 0x79, 0x55, 0x6, 0xee, 0x9f,
   488  		0x93, 0xfc, 0xbe, 0xf8, 0x3c, 0x67, 0xe1, 0x67, 0x16, 0xcb,
   489  		0xd1, 0x15, 0x8d, 0xde, 0xd4, 0x20, 0xb3, 0x1, 0x54, 0x18,
   490  		0x66, 0xc5, 0x24, 0x2f, 0xd, 0x88, 0xef, 0x32, 0x3f, 0x74,
   491  		0xd9, 0x56, 0x74, 0x1f, 0x17, 0xa7, 0xbb, 0xfe, 0xdf, 0xf,
   492  		0x6c, 0x5f, 0x93, 0x77, 0x27, 0xf5, 0xae, 0x27, 0x52, 0x8e,
   493  		0x3b, 0x99, 0xb6, 0xea, 0x44, 0x65, 0x1d, 0xa, 0x3b, 0x13,
   494  		0x34, 0xf7, 0xf7, 0xbe, 0x20,
   495  	},
   496  }
   497  
   498  var privateKey = &Block{Type: "RSA PRIVATE KEY",
   499  	Headers: map[string]string{"DEK-Info": "DES-EDE3-CBC,80C7C7A09690757A", "Proc-Type": "4,ENCRYPTED"},
   500  	Bytes: []uint8{0x79, 0xa, 0x79, 0x66, 0x41, 0xfa, 0xb,
   501  		0x21, 0xc1, 0xcf, 0xb0, 0x59, 0x7d, 0x43, 0xf1, 0xc8, 0xb0,
   502  		0x82, 0x99, 0xfb, 0x6c, 0x4, 0x9e, 0xc7, 0x96, 0xa1, 0x9b,
   503  		0xf0, 0xb7, 0x76, 0xd5, 0xc4, 0xb0, 0x9f, 0x35, 0x99, 0xe3,
   504  		0xf4, 0x88, 0x96, 0x1c, 0xab, 0x52, 0xdb, 0x1f, 0xc3, 0xb5,
   505  		0x51, 0xd9, 0x34, 0xf0, 0x3, 0xea, 0x1d, 0xa3, 0xd7, 0xb1,
   506  		0xec, 0x67, 0x71, 0x39, 0x36, 0x87, 0xf2, 0x86, 0x45, 0xba,
   507  		0x62, 0x11, 0xa2, 0x21, 0x23, 0x1e, 0xc9, 0x3c, 0x53, 0xb0,
   508  		0x61, 0x9e, 0xda, 0x7e, 0x7a, 0x49, 0xf, 0x3f, 0xbf, 0x71,
   509  		0xba, 0x79, 0xcd, 0xee, 0x16, 0xfb, 0x86, 0x48, 0x6b, 0xc8,
   510  		0x60, 0xd0, 0x66, 0x0, 0x3b, 0xb3, 0x67, 0x10, 0x1d, 0xe,
   511  		0xf5, 0xbf, 0x78, 0x30, 0x4f, 0x60, 0x40, 0x8, 0x7, 0xed,
   512  		0xdb, 0xa8, 0xc2, 0x8d, 0xb3, 0x35, 0xc2, 0x3, 0x73, 0x6,
   513  		0x72, 0x7c, 0x33, 0x44, 0x73, 0x9f, 0xaf, 0x18, 0x5a, 0xa6,
   514  		0x8f, 0xb5, 0xd0, 0x6e, 0xf2, 0xa6, 0xff, 0xcd, 0x54, 0x79,
   515  		0x24, 0x1d, 0x66, 0x9e, 0xab, 0xd3, 0x49, 0xb1, 0x6c, 0x7c,
   516  		0x5e, 0x72, 0x31, 0xce, 0xa8, 0xd9, 0x64, 0x3d, 0x8c, 0x90,
   517  		0xa5, 0xe8, 0xac, 0xa9, 0x9c, 0xc9, 0x7e, 0x6, 0x92, 0xfe,
   518  		0x76, 0x5b, 0xdd, 0x8d, 0x85, 0x4a, 0xe2, 0x5f, 0x65, 0x62,
   519  		0xc0, 0x75, 0x1e, 0xcd, 0xdd, 0xfb, 0x30, 0xc1, 0x6d, 0x6c,
   520  		0x68, 0xb3, 0xcd, 0x7c, 0xcf, 0x38, 0x52, 0xf3, 0xfc, 0xba,
   521  		0x78, 0x87, 0xe2, 0x48, 0x6d, 0xbb, 0x72, 0xaa, 0xdb, 0x85,
   522  		0x44, 0x5b, 0x9a, 0x8, 0x92, 0x7c, 0x35, 0xe3, 0x9d, 0xc2,
   523  		0xb8, 0x9b, 0xfa, 0x4b, 0x71, 0xe, 0xe6, 0x98, 0x12, 0xfa,
   524  		0x98, 0x53, 0xab, 0xdc, 0xf8, 0xf8, 0x8d, 0xea, 0x73, 0x80,
   525  		0xe8, 0x85, 0x44, 0xbe, 0x8c, 0x28, 0x4f, 0xff, 0x87, 0xad,
   526  		0x9f, 0x66, 0xf2, 0x35, 0x12, 0xb6, 0x2b, 0xf1, 0x5b, 0xa7,
   527  		0x1c, 0x4c, 0xa4, 0x80, 0xa3, 0x61, 0xa, 0x10, 0xef, 0x6f,
   528  		0x54, 0x4e, 0xe8, 0xb1, 0x1f, 0xa8, 0xa0, 0x6e, 0xf8, 0x8b,
   529  		0xf0, 0x4c, 0x1e, 0x9f, 0x6, 0x15, 0xb7, 0x4c, 0x22, 0xcc,
   530  		0x9d, 0x53, 0xd8, 0x56, 0x86, 0x30, 0x3, 0xe7, 0xc7, 0x35,
   531  		0x39, 0x99, 0x66, 0x6f, 0x1, 0x12, 0x89, 0xe5, 0x20, 0xc7,
   532  		0xc8, 0xf8, 0xa9, 0x2d, 0x8d, 0x65, 0x20, 0xe0, 0xe8, 0x9a,
   533  		0xf8, 0xd2, 0x3a, 0xbc, 0xa7, 0xf, 0xa4, 0x5a, 0x31, 0x85,
   534  		0x29, 0xe5, 0x1a, 0x0, 0xad, 0xbd, 0xf1, 0x1a, 0xab, 0x9f,
   535  		0xc7, 0xe2, 0x41, 0xc9, 0xa7, 0xde, 0x5e, 0x3a, 0x99, 0xc5,
   536  		0xb0, 0xbb, 0xe2, 0xc3, 0x6b, 0x1e, 0x1c, 0xd9, 0x33, 0xfc,
   537  		0xbc, 0x49, 0x31, 0x13, 0xf5, 0x5f, 0x8d, 0xbc, 0xf8, 0x3a,
   538  		0x58, 0x5b, 0xf4, 0x3, 0xff, 0x42, 0x54, 0xb4, 0x94, 0xae,
   539  		0xb, 0xfa, 0xbd, 0x15, 0x41, 0xcb, 0xe9, 0x12, 0x37, 0xbb,
   540  		0xf0, 0x2c, 0xae, 0xff, 0x29, 0x9, 0xbe, 0x3e, 0xf, 0xb8,
   541  		0xb5, 0x8d, 0x6f, 0xc0, 0x30, 0x87, 0x49, 0x4e, 0xdc, 0x9c,
   542  		0x38, 0x6b, 0x1b, 0x3f, 0x14, 0x0, 0xef, 0x21, 0xcc, 0x5a,
   543  		0xe8, 0xc7, 0x99, 0xe6, 0xf5, 0x5, 0x38, 0x87, 0x70, 0xbd,
   544  		0xec, 0xdc, 0xaa, 0xc9, 0xbb, 0x5b, 0xc3, 0x56, 0xbb, 0x21,
   545  		0xbf, 0x17, 0xe7, 0xcf, 0xbd, 0x4a, 0x4d, 0xe3, 0x67, 0x64,
   546  		0x7f, 0x14, 0x6c, 0xea, 0x93, 0xe6, 0x2e, 0xdf, 0x3c, 0x6c,
   547  		0x97, 0xb5, 0x8d, 0x57, 0x25, 0xd7, 0x5c, 0x6c, 0x8f, 0xd0,
   548  		0xea, 0xd5, 0xdf, 0xc0, 0x71, 0x6c, 0x65, 0xcd, 0xb4, 0x4f,
   549  		0x34, 0x9d, 0xb1, 0x52, 0xc1, 0xb7, 0x9, 0x2c, 0x51, 0xa7,
   550  		0x29, 0x6c, 0x3a, 0x20, 0x70, 0x45, 0x4c, 0x72, 0xd9, 0xcd,
   551  		0xac, 0x1f, 0x5, 0x22, 0xb0, 0x77, 0xbd, 0x91, 0x2f, 0xf5,
   552  		0xd, 0x19, 0xd5, 0x57, 0x98, 0xee, 0x79, 0x93, 0xa4, 0x5f,
   553  		0xba, 0x6b, 0xec, 0xf6, 0x3f, 0xb6, 0x9c, 0x2f, 0xb8, 0xfa,
   554  		0x3, 0xa3, 0xeb, 0xdf, 0xea, 0xbc, 0x3f, 0xd0, 0x8f, 0x88,
   555  		0xf0, 0xbb, 0xcc, 0x5a, 0x27, 0x57, 0x3b, 0x95, 0x3f, 0x20,
   556  		0x7c, 0x19, 0xc8, 0x46, 0x47, 0x68, 0x72, 0xb7, 0x28, 0x8e,
   557  		0x56, 0x9b, 0x83, 0xf7, 0xe9, 0x3c, 0x85, 0xcb, 0xb0, 0x65,
   558  		0x60, 0x1a, 0x52, 0x85, 0x6d, 0x58, 0x84, 0x39, 0xd9, 0xa2,
   559  		0x92, 0xd2, 0x9d, 0x7d, 0x1b, 0xdf, 0x61, 0x85, 0xbf, 0x88,
   560  		0x54, 0x3, 0x42, 0xe1, 0xa9, 0x24, 0x74, 0x75, 0x78, 0x48,
   561  		0xff, 0x22, 0xec, 0xc5, 0x4d, 0x66, 0x17, 0xd4, 0x9a,
   562  	},
   563  }
   564  
   565  var privateKey2 = &Block{
   566  	Type: "RSA PRIVATE KEY",
   567  	Headers: map[string]string{
   568  		"Proc-Type":      "4,ENCRYPTED",
   569  		"DEK-Info":       "AES-128-CBC,BFCD243FEDBB40A4AA6DDAA1335473A4",
   570  		"Content-Domain": "RFC822",
   571  	},
   572  	Bytes: []uint8{
   573  		0xa8, 0x35, 0xcc, 0x2b, 0xb9, 0xcb, 0x21, 0xab, 0xc0,
   574  		0x9d, 0x76, 0x61, 0x0, 0xf4, 0x81, 0xad, 0x69, 0xd2,
   575  		0xc0, 0x42, 0x41, 0x3b, 0xe4, 0x3c, 0xaf, 0x59, 0x5e,
   576  		0x6d, 0x2a, 0x3c, 0x9c, 0xa1, 0xa4, 0x5e, 0x68, 0x37,
   577  		0xc4, 0x8c, 0x70, 0x1c, 0xa9, 0x18, 0xe6, 0xc2, 0x2b,
   578  		0x8a, 0x91, 0xdc, 0x2d, 0x1f, 0x8, 0x23, 0x39, 0xf1,
   579  		0x4b, 0x8b, 0x1b, 0x2f, 0x46, 0xb, 0xb2, 0x26, 0xba,
   580  		0x4f, 0x40, 0x80, 0x39, 0xc4, 0xb1, 0xcb, 0x3b, 0xb4,
   581  		0x65, 0x3f, 0x1b, 0xb2, 0xf7, 0x8, 0xd2, 0xc6, 0xd5,
   582  		0xa8, 0x9f, 0x23, 0x69, 0xb6, 0x3d, 0xf9, 0xac, 0x1c,
   583  		0xb3, 0x13, 0x87, 0x64, 0x4, 0x37, 0xdb, 0x40, 0xc8,
   584  		0x82, 0xc, 0xd0, 0xf8, 0x21, 0x7c, 0xdc, 0xbd, 0x9, 0x4,
   585  		0x20, 0x16, 0xb0, 0x97, 0xe2, 0x6d, 0x56, 0x1d, 0xe3,
   586  		0xec, 0xf0, 0xfc, 0xe2, 0x56, 0xad, 0xa4, 0x3, 0x70,
   587  		0x6d, 0x63, 0x3c, 0x1, 0xbe, 0x3e, 0x28, 0x38, 0x6f,
   588  		0xc0, 0xe6, 0xfd, 0x85, 0xd1, 0x53, 0xa8, 0x9b, 0xcb,
   589  		0xd4, 0x4, 0xb1, 0x73, 0xb9, 0x73, 0x32, 0xd6, 0x7a,
   590  		0xc6, 0x29, 0x25, 0xa5, 0xda, 0x17, 0x93, 0x7a, 0x10,
   591  		0xe8, 0x41, 0xfb, 0xa5, 0x17, 0x20, 0xf8, 0x4e, 0xe9,
   592  		0xe3, 0x8f, 0x51, 0x20, 0x13, 0xbb, 0xde, 0xb7, 0x93,
   593  		0xae, 0x13, 0x8a, 0xf6, 0x9, 0xf4, 0xa6, 0x41, 0xe0,
   594  		0x2b, 0x51, 0x1a, 0x30, 0x38, 0xd, 0xb1, 0x3b, 0x67,
   595  		0x87, 0x64, 0xf5, 0xca, 0x32, 0x67, 0xd1, 0xc8, 0xa5,
   596  		0x3d, 0x23, 0x72, 0xc4, 0x6, 0xaf, 0x8f, 0x7b, 0x26,
   597  		0xac, 0x3c, 0x75, 0x91, 0xa1, 0x0, 0x13, 0xc6, 0x5c,
   598  		0x49, 0xd5, 0x3c, 0xe7, 0xb2, 0xb2, 0x99, 0xe0, 0xd5,
   599  		0x25, 0xfa, 0xe2, 0x12, 0x80, 0x37, 0x85, 0xcf, 0x92,
   600  		0xca, 0x1b, 0x9f, 0xf3, 0x4e, 0xd8, 0x80, 0xef, 0x3c,
   601  		0xce, 0xcd, 0xf5, 0x90, 0x9e, 0xf9, 0xa7, 0xb2, 0xc,
   602  		0x49, 0x4, 0xf1, 0x9, 0x8f, 0xea, 0x63, 0xd2, 0x70,
   603  		0xbb, 0x86, 0xbf, 0x34, 0xab, 0xb2, 0x3, 0xb1, 0x59,
   604  		0x33, 0x16, 0x17, 0xb0, 0xdb, 0x77, 0x38, 0xf4, 0xb4,
   605  		0x94, 0xb, 0x25, 0x16, 0x7e, 0x22, 0xd4, 0xf9, 0x22,
   606  		0xb9, 0x78, 0xa3, 0x4, 0x84, 0x4, 0xd2, 0xda, 0x84,
   607  		0x2d, 0x63, 0xdd, 0xf8, 0x50, 0x6a, 0xf6, 0xe3, 0xf5,
   608  		0x65, 0x40, 0x7c, 0xa9,
   609  	},
   610  }
   611  
   612  var pemPrivateKey2 = testingKey(`-----BEGIN RSA TESTING KEY-----
   613  Proc-Type: 4,ENCRYPTED
   614  Content-Domain: RFC822
   615  DEK-Info: AES-128-CBC,BFCD243FEDBB40A4AA6DDAA1335473A4
   616  
   617  qDXMK7nLIavAnXZhAPSBrWnSwEJBO+Q8r1lebSo8nKGkXmg3xIxwHKkY5sIripHc
   618  LR8IIznxS4sbL0YLsia6T0CAOcSxyzu0ZT8bsvcI0sbVqJ8jabY9+awcsxOHZAQ3
   619  20DIggzQ+CF83L0JBCAWsJfibVYd4+zw/OJWraQDcG1jPAG+Pig4b8Dm/YXRU6ib
   620  y9QEsXO5czLWesYpJaXaF5N6EOhB+6UXIPhO6eOPUSATu963k64TivYJ9KZB4CtR
   621  GjA4DbE7Z4dk9coyZ9HIpT0jcsQGr497Jqw8dZGhABPGXEnVPOeyspng1SX64hKA
   622  N4XPksobn/NO2IDvPM7N9ZCe+aeyDEkE8QmP6mPScLuGvzSrsgOxWTMWF7Dbdzj0
   623  tJQLJRZ+ItT5Irl4owSEBNLahC1j3fhQavbj9WVAfKk=
   624  -----END RSA TESTING KEY-----
   625  `)
   626  
   627  func TestBadEncode(t *testing.T) {
   628  	b := &Block{Type: "BAD", Headers: map[string]string{"X:Y": "Z"}}
   629  	var buf bytes.Buffer
   630  	if err := Encode(&buf, b); err == nil {
   631  		t.Fatalf("Encode did not report invalid header")
   632  	}
   633  	if buf.Len() != 0 {
   634  		t.Fatalf("Encode wrote data before reporting invalid header")
   635  	}
   636  	if data := EncodeToMemory(b); data != nil {
   637  		t.Fatalf("EncodeToMemory returned non-nil data")
   638  	}
   639  }
   640  
   641  func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
   642  
   643  func TestDecodeStrangeCases(t *testing.T) {
   644  	sentinelType := "TEST BLOCK"
   645  	sentinelBytes := []byte("hello")
   646  	for _, tc := range []struct {
   647  		name string
   648  		pem  string
   649  	}{
   650  		{
   651  			name: "invalid section (not base64)",
   652  			pem: `-----BEGIN COMMENT-----
   653  foo foo foo
   654  -----END COMMENT-----
   655  -----BEGIN TEST BLOCK-----
   656  aGVsbG8=
   657  -----END TEST BLOCK-----`,
   658  		},
   659  		{
   660  			name: "leading garbage on block",
   661  			pem: `foo foo foo-----BEGIN CERTIFICATE-----
   662  MCowBQYDK2VwAyEApVjJeLW5MoP6uR3+OeITokM+rBDng6dgl1vvhcy+wws=
   663  -----END PUBLIC KEY-----
   664  -----BEGIN TEST BLOCK-----
   665  aGVsbG8=
   666  -----END TEST BLOCK-----`,
   667  		},
   668  		{
   669  			name: "leading garbage",
   670  			pem: `foo foo foo
   671  -----BEGIN TEST BLOCK-----
   672  aGVsbG8=
   673  -----END TEST BLOCK-----`,
   674  		},
   675  		{
   676  			name: "leading partial block",
   677  			pem: `foo foo foo
   678  -----END COMMENT-----
   679  -----BEGIN TEST BLOCK-----
   680  aGVsbG8=
   681  -----END TEST BLOCK-----`,
   682  		},
   683  		{
   684  			name: "multiple BEGIN",
   685  			pem: `-----BEGIN TEST BLOCK-----
   686  -----BEGIN TEST BLOCK-----
   687  -----BEGIN TEST BLOCK-----
   688  aGVsbG8=
   689  -----END TEST BLOCK-----`,
   690  		},
   691  		{
   692  			name: "multiple END",
   693  			pem: `-----BEGIN TEST BLOCK-----
   694  aGVsbG8=
   695  -----END TEST BLOCK-----
   696  -----END TEST BLOCK-----
   697  -----END TEST BLOCK-----`,
   698  		},
   699  		{
   700  			name: "leading malformed BEGIN",
   701  			pem: `-----BEGIN PUBLIC KEY
   702  aGVsbG8=
   703  -----END PUBLIC KEY-----
   704  -----BEGIN TEST BLOCK-----
   705  aGVsbG8=
   706  -----END TEST BLOCK-----`,
   707  		},
   708  	} {
   709  		t.Run(tc.name, func(t *testing.T) {
   710  			block, _ := Decode([]byte(tc.pem))
   711  			if block == nil {
   712  				t.Fatal("expected valid block")
   713  			}
   714  			if block.Type != sentinelType {
   715  				t.Fatalf("unexpected block returned, got type %q, want type %q", block.Type, sentinelType)
   716  			}
   717  			if !bytes.Equal(block.Bytes, sentinelBytes) {
   718  				t.Fatalf("unexpected block content, got %x, want %x", block.Bytes, sentinelBytes)
   719  			}
   720  		})
   721  	}
   722  }
   723  
   724  func TestJustEnd(t *testing.T) {
   725  	pemData := `
   726  -----END PUBLIC KEY-----`
   727  
   728  	block, _ := Decode([]byte(pemData))
   729  	if block != nil {
   730  		t.Fatal("unexpected block")
   731  	}
   732  }
   733  
   734  func FuzzDecode(f *testing.F) {
   735  	f.Fuzz(func(t *testing.T, data []byte) {
   736  		Decode(data)
   737  	})
   738  }
   739  
   740  func TestMissingEndTrailer(t *testing.T) {
   741  	Decode([]byte{0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20})
   742  }
   743  

View as plain text