1
2
3
4
5 package asn1
6
7 import (
8 "bytes"
9 "encoding/hex"
10 "errors"
11 "fmt"
12 "math"
13 "math/big"
14 "reflect"
15 "runtime"
16 "strings"
17 "testing"
18 "time"
19 )
20
21 type boolTest struct {
22 in []byte
23 ok bool
24 out bool
25 }
26
27 var boolTestData = []boolTest{
28 {[]byte{0x00}, true, false},
29 {[]byte{0xff}, true, true},
30 {[]byte{0x00, 0x00}, false, false},
31 {[]byte{0xff, 0xff}, false, false},
32 {[]byte{0x01}, false, false},
33 }
34
35 func TestParseBool(t *testing.T) {
36 for i, test := range boolTestData {
37 ret, err := parseBool(test.in)
38 if (err == nil) != test.ok {
39 t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
40 }
41 if test.ok && ret != test.out {
42 t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
43 }
44 }
45 }
46
47 type int64Test struct {
48 in []byte
49 ok bool
50 out int64
51 }
52
53 var int64TestData = []int64Test{
54 {[]byte{0x00}, true, 0},
55 {[]byte{0x7f}, true, 127},
56 {[]byte{0x00, 0x80}, true, 128},
57 {[]byte{0x01, 0x00}, true, 256},
58 {[]byte{0x80}, true, -128},
59 {[]byte{0xff, 0x7f}, true, -129},
60 {[]byte{0xff}, true, -1},
61 {[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, true, -9223372036854775808},
62 {[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, false, 0},
63 {[]byte{}, false, 0},
64 {[]byte{0x00, 0x7f}, false, 0},
65 {[]byte{0xff, 0xf0}, false, 0},
66 }
67
68 func TestParseInt64(t *testing.T) {
69 for i, test := range int64TestData {
70 ret, err := parseInt64(test.in)
71 if (err == nil) != test.ok {
72 t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
73 }
74 if test.ok && ret != test.out {
75 t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
76 }
77 }
78 }
79
80 type int32Test struct {
81 in []byte
82 ok bool
83 out int32
84 }
85
86 var int32TestData = []int32Test{
87 {[]byte{0x00}, true, 0},
88 {[]byte{0x7f}, true, 127},
89 {[]byte{0x00, 0x80}, true, 128},
90 {[]byte{0x01, 0x00}, true, 256},
91 {[]byte{0x80}, true, -128},
92 {[]byte{0xff, 0x7f}, true, -129},
93 {[]byte{0xff}, true, -1},
94 {[]byte{0x80, 0x00, 0x00, 0x00}, true, -2147483648},
95 {[]byte{0x80, 0x00, 0x00, 0x00, 0x00}, false, 0},
96 {[]byte{}, false, 0},
97 {[]byte{0x00, 0x7f}, false, 0},
98 {[]byte{0xff, 0xf0}, false, 0},
99 }
100
101 func TestParseInt32(t *testing.T) {
102 for i, test := range int32TestData {
103 ret, err := parseInt32(test.in)
104 if (err == nil) != test.ok {
105 t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
106 }
107 if test.ok && ret != test.out {
108 t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
109 }
110 }
111 }
112
113 var bigIntTests = []struct {
114 in []byte
115 ok bool
116 base10 string
117 }{
118 {[]byte{0xff}, true, "-1"},
119 {[]byte{0x00}, true, "0"},
120 {[]byte{0x01}, true, "1"},
121 {[]byte{0x00, 0xff}, true, "255"},
122 {[]byte{0xff, 0x00}, true, "-256"},
123 {[]byte{0x01, 0x00}, true, "256"},
124 {[]byte{}, false, ""},
125 {[]byte{0x00, 0x7f}, false, ""},
126 {[]byte{0xff, 0xf0}, false, ""},
127 }
128
129 func TestParseBigInt(t *testing.T) {
130 for i, test := range bigIntTests {
131 ret, err := parseBigInt(test.in)
132 if (err == nil) != test.ok {
133 t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
134 }
135 if test.ok {
136 if ret.String() != test.base10 {
137 t.Errorf("#%d: bad result from %x, got %s want %s", i, test.in, ret.String(), test.base10)
138 }
139 e, err := makeBigInt(ret)
140 if err != nil {
141 t.Errorf("%d: err=%q", i, err)
142 continue
143 }
144 result := make([]byte, e.Len())
145 e.Encode(result)
146 if !bytes.Equal(result, test.in) {
147 t.Errorf("#%d: got %x from marshaling %s, want %x", i, result, ret, test.in)
148 }
149 }
150 }
151 }
152
153 type bitStringTest struct {
154 in []byte
155 ok bool
156 out []byte
157 bitLength int
158 }
159
160 var bitStringTestData = []bitStringTest{
161 {[]byte{}, false, []byte{}, 0},
162 {[]byte{0x00}, true, []byte{}, 0},
163 {[]byte{0x07, 0x00}, true, []byte{0x00}, 1},
164 {[]byte{0x07, 0x01}, false, []byte{}, 0},
165 {[]byte{0x07, 0x40}, false, []byte{}, 0},
166 {[]byte{0x08, 0x00}, false, []byte{}, 0},
167 }
168
169 func TestBitString(t *testing.T) {
170 for i, test := range bitStringTestData {
171 ret, err := parseBitString(test.in)
172 if (err == nil) != test.ok {
173 t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
174 }
175 if err == nil {
176 if test.bitLength != ret.BitLength || !bytes.Equal(ret.Bytes, test.out) {
177 t.Errorf("#%d: Bad result: %v (expected %v %v)", i, ret, test.out, test.bitLength)
178 }
179 }
180 }
181 }
182
183 func TestBitStringAt(t *testing.T) {
184 bs := BitString{[]byte{0x82, 0x40}, 16}
185 if bs.At(0) != 1 {
186 t.Error("#1: Failed")
187 }
188 if bs.At(1) != 0 {
189 t.Error("#2: Failed")
190 }
191 if bs.At(6) != 1 {
192 t.Error("#3: Failed")
193 }
194 if bs.At(9) != 1 {
195 t.Error("#4: Failed")
196 }
197 if bs.At(-1) != 0 {
198 t.Error("#5: Failed")
199 }
200 if bs.At(17) != 0 {
201 t.Error("#6: Failed")
202 }
203 }
204
205 type bitStringRightAlignTest struct {
206 in []byte
207 inlen int
208 out []byte
209 }
210
211 var bitStringRightAlignTests = []bitStringRightAlignTest{
212 {[]byte{0x80}, 1, []byte{0x01}},
213 {[]byte{0x80, 0x80}, 9, []byte{0x01, 0x01}},
214 {[]byte{}, 0, []byte{}},
215 {[]byte{0xce}, 8, []byte{0xce}},
216 {[]byte{0xce, 0x47}, 16, []byte{0xce, 0x47}},
217 {[]byte{0x34, 0x50}, 12, []byte{0x03, 0x45}},
218 }
219
220 func TestBitStringRightAlign(t *testing.T) {
221 for i, test := range bitStringRightAlignTests {
222 bs := BitString{test.in, test.inlen}
223 out := bs.RightAlign()
224 if !bytes.Equal(out, test.out) {
225 t.Errorf("#%d got: %x want: %x", i, out, test.out)
226 }
227 }
228 }
229
230 type objectIdentifierTest struct {
231 in []byte
232 ok bool
233 out ObjectIdentifier
234 }
235
236 var objectIdentifierTestData = []objectIdentifierTest{
237 {[]byte{}, false, []int{}},
238 {[]byte{85}, true, []int{2, 5}},
239 {[]byte{85, 0x02}, true, []int{2, 5, 2}},
240 {[]byte{85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}},
241 {[]byte{0x81, 0x34, 0x03}, true, []int{2, 100, 3}},
242 {[]byte{85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}},
243 }
244
245 func TestObjectIdentifier(t *testing.T) {
246 for i, test := range objectIdentifierTestData {
247 ret, err := parseObjectIdentifier(test.in)
248 if (err == nil) != test.ok {
249 t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
250 }
251 if err == nil {
252 if !reflect.DeepEqual(test.out, ret) {
253 t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
254 }
255 }
256 }
257
258 if s := ObjectIdentifier([]int{1, 2, 3, 4}).String(); s != "1.2.3.4" {
259 t.Errorf("bad ObjectIdentifier.String(). Got %s, want 1.2.3.4", s)
260 }
261 }
262
263 type timeTest struct {
264 in string
265 ok bool
266 out time.Time
267 }
268
269 var utcTestData = []timeTest{
270 {"910506164540-0700", true, time.Date(1991, 05, 06, 16, 45, 40, 0, time.FixedZone("", -7*60*60))},
271 {"910506164540+0730", true, time.Date(1991, 05, 06, 16, 45, 40, 0, time.FixedZone("", 7*60*60+30*60))},
272 {"910506234540Z", true, time.Date(1991, 05, 06, 23, 45, 40, 0, time.UTC)},
273 {"9105062345Z", true, time.Date(1991, 05, 06, 23, 45, 0, 0, time.UTC)},
274 {"5105062345Z", true, time.Date(1951, 05, 06, 23, 45, 0, 0, time.UTC)},
275 {"a10506234540Z", false, time.Time{}},
276 {"91a506234540Z", false, time.Time{}},
277 {"9105a6234540Z", false, time.Time{}},
278 {"910506a34540Z", false, time.Time{}},
279 {"910506334a40Z", false, time.Time{}},
280 {"91050633444aZ", false, time.Time{}},
281 {"910506334461Z", false, time.Time{}},
282 {"910506334400Za", false, time.Time{}},
283
285 {"000100000000Z", false, time.Time{}},
286 {"101302030405Z", false, time.Time{}},
287 {"100002030405Z", false, time.Time{}},
288 {"100100030405Z", false, time.Time{}},
289 {"100132030405Z", false, time.Time{}},
290 {"100231030405Z", false, time.Time{}},
291 {"100102240405Z", false, time.Time{}},
292 {"100102036005Z", false, time.Time{}},
293 {"100102030460Z", false, time.Time{}},
294 {"-100102030410Z", false, time.Time{}},
295 {"10-0102030410Z", false, time.Time{}},
296 {"10-0002030410Z", false, time.Time{}},
297 {"1001-02030410Z", false, time.Time{}},
298 {"100102-030410Z", false, time.Time{}},
299 {"10010203-0410Z", false, time.Time{}},
300 {"1001020304-10Z", false, time.Time{}},
301 }
302
303 func TestUTCTime(t *testing.T) {
304 for i, test := range utcTestData {
305 ret, err := parseUTCTime([]byte(test.in))
306 if err != nil {
307 if test.ok {
308 t.Errorf("#%d: parseUTCTime(%q) = error %v", i, test.in, err)
309 }
310 continue
311 }
312 if !test.ok {
313 t.Errorf("#%d: parseUTCTime(%q) succeeded, should have failed", i, test.in)
314 continue
315 }
316 const format = "Jan _2 15:04:05 -0700 2006"
317 have := ret.Format(format)
318 want := test.out.Format(format)
319 if have != want {
320 t.Errorf("#%d: parseUTCTime(%q) = %s, want %s", i, test.in, have, want)
321 }
322 }
323 }
324
325 var generalizedTimeTestData = []timeTest{
326 {"20100102030405Z", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.UTC)},
327 {"20100102030405", false, time.Time{}},
328 {"20100102030405.123456Z", true, time.Date(2010, 01, 02, 03, 04, 05, 123456e3, time.UTC)},
329 {"20100102030405.123456", false, time.Time{}},
330 {"20100102030405.Z", false, time.Time{}},
331 {"20100102030405.", false, time.Time{}},
332 {"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))},
333 {"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))},
334
336 {"00000100000000Z", false, time.Time{}},
337 {"20101302030405Z", false, time.Time{}},
338 {"20100002030405Z", false, time.Time{}},
339 {"20100100030405Z", false, time.Time{}},
340 {"20100132030405Z", false, time.Time{}},
341 {"20100231030405Z", false, time.Time{}},
342 {"20100102240405Z", false, time.Time{}},
343 {"20100102036005Z", false, time.Time{}},
344 {"20100102030460Z", false, time.Time{}},
345 {"-20100102030410Z", false, time.Time{}},
346 {"2010-0102030410Z", false, time.Time{}},
347 {"2010-0002030410Z", false, time.Time{}},
348 {"201001-02030410Z", false, time.Time{}},
349 {"20100102-030410Z", false, time.Time{}},
350 {"2010010203-0410Z", false, time.Time{}},
351 {"201001020304-10Z", false, time.Time{}},
352 }
353
354 func TestGeneralizedTime(t *testing.T) {
355 for i, test := range generalizedTimeTestData {
356 ret, err := parseGeneralizedTime([]byte(test.in))
357 if (err == nil) != test.ok {
358 t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
359 }
360 if err == nil {
361 if !reflect.DeepEqual(test.out, ret) {
362 t.Errorf("#%d: Bad result: %q → %v (expected %v)", i, test.in, ret, test.out)
363 }
364 }
365 }
366 }
367
368 type tagAndLengthTest struct {
369 in []byte
370 ok bool
371 out tagAndLength
372 }
373
374 var tagAndLengthData = []tagAndLengthTest{
375 {[]byte{0x80, 0x01}, true, tagAndLength{2, 0, 1, false}},
376 {[]byte{0xa0, 0x01}, true, tagAndLength{2, 0, 1, true}},
377 {[]byte{0x02, 0x00}, true, tagAndLength{0, 2, 0, false}},
378 {[]byte{0xfe, 0x00}, true, tagAndLength{3, 30, 0, true}},
379 {[]byte{0x1f, 0x1f, 0x00}, true, tagAndLength{0, 31, 0, false}},
380 {[]byte{0x1f, 0x81, 0x00, 0x00}, true, tagAndLength{0, 128, 0, false}},
381 {[]byte{0x1f, 0x81, 0x80, 0x01, 0x00}, true, tagAndLength{0, 0x4001, 0, false}},
382 {[]byte{0x00, 0x81, 0x80}, true, tagAndLength{0, 0, 128, false}},
383 {[]byte{0x00, 0x82, 0x01, 0x00}, true, tagAndLength{0, 0, 256, false}},
384 {[]byte{0x00, 0x83, 0x01, 0x00}, false, tagAndLength{}},
385 {[]byte{0x1f, 0x85}, false, tagAndLength{}},
386 {[]byte{0x30, 0x80}, false, tagAndLength{}},
387
388 {[]byte{0xa0, 0x82, 0x00, 0xff}, false, tagAndLength{}},
389
390 {[]byte{0xa0, 0x84, 0x7f, 0xff, 0xff, 0xff}, true, tagAndLength{2, 0, 0x7fffffff, true}},
391
392 {[]byte{0xa0, 0x84, 0x80, 0x00, 0x00, 0x00}, false, tagAndLength{}},
393
394 {[]byte{0xa0, 0x81, 0x7f}, false, tagAndLength{}},
395
396 {[]byte{0x1f, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00}, false, tagAndLength{}},
397
398 {[]byte{0x1f, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x00}, true, tagAndLength{tag: math.MaxInt32}},
399
400 {[]byte{0x1f, 0x1e, 0x00}, false, tagAndLength{}},
401 }
402
403 func TestParseTagAndLength(t *testing.T) {
404 for i, test := range tagAndLengthData {
405 tagAndLength, _, err := parseTagAndLength(test.in, 0)
406 if (err == nil) != test.ok {
407 t.Errorf("#%d: Incorrect error result (did pass? %v, expected: %v)", i, err == nil, test.ok)
408 }
409 if err == nil && !reflect.DeepEqual(test.out, tagAndLength) {
410 t.Errorf("#%d: Bad result: %v (expected %v)", i, tagAndLength, test.out)
411 }
412 }
413 }
414
415 type parseFieldParametersTest struct {
416 in string
417 out fieldParameters
418 }
419
420 func newInt(n int) *int { return &n }
421
422 func newInt64(n int64) *int64 { return &n }
423
424 func newString(s string) *string { return &s }
425
426 func newBool(b bool) *bool { return &b }
427
428 var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParametersTest{
429 {"", fieldParameters{}},
430 {"ia5", fieldParameters{stringType: TagIA5String}},
431 {"generalized", fieldParameters{timeType: TagGeneralizedTime}},
432 {"utc", fieldParameters{timeType: TagUTCTime}},
433 {"printable", fieldParameters{stringType: TagPrintableString}},
434 {"numeric", fieldParameters{stringType: TagNumericString}},
435 {"optional", fieldParameters{optional: true}},
436 {"explicit", fieldParameters{explicit: true, tag: new(int)}},
437 {"application", fieldParameters{application: true, tag: new(int)}},
438 {"private", fieldParameters{private: true, tag: new(int)}},
439 {"optional,explicit", fieldParameters{optional: true, explicit: true, tag: new(int)}},
440 {"default:42", fieldParameters{defaultValue: newInt64(42)}},
441 {"tag:17", fieldParameters{tag: newInt(17)}},
442 {"optional,explicit,default:42,tag:17", fieldParameters{optional: true, explicit: true, defaultValue: newInt64(42), tag: newInt(17)}},
443 {"optional,explicit,default:42,tag:17,rubbish1", fieldParameters{optional: true, explicit: true, application: false, defaultValue: newInt64(42), tag: newInt(17), stringType: 0, timeType: 0, set: false, omitEmpty: false}},
444 {"set", fieldParameters{set: true}},
445 }
446
447 func TestParseFieldParameters(t *testing.T) {
448 for i, test := range parseFieldParametersTestData {
449 f := parseFieldParameters(test.in)
450 if !reflect.DeepEqual(f, test.out) {
451 t.Errorf("#%d: Bad result: %v (expected %v)", i, f, test.out)
452 }
453 }
454 }
455
456 type TestObjectIdentifierStruct struct {
457 OID ObjectIdentifier
458 }
459
460 type TestContextSpecificTags struct {
461 A int `asn1:"tag:1"`
462 }
463
464 type TestContextSpecificTags2 struct {
465 A int `asn1:"explicit,tag:1"`
466 B int
467 }
468
469 type TestContextSpecificTags3 struct {
470 S string `asn1:"tag:1,utf8"`
471 }
472
473 type TestElementsAfterString struct {
474 S string
475 A, B int
476 }
477
478 type TestBigInt struct {
479 X *big.Int
480 }
481
482 type TestSet struct {
483 Ints []int `asn1:"set"`
484 }
485
486 var unmarshalTestData = []struct {
487 in []byte
488 out any
489 }{
490 {[]byte{0x02, 0x01, 0x42}, newInt(0x42)},
491 {[]byte{0x05, 0x00}, &RawValue{0, 5, false, []byte{}, []byte{0x05, 0x00}}},
492 {[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}},
493 {[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}},
494 {[]byte{0x30, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &[]int{1, 2, 3}},
495 {[]byte{0x02, 0x01, 0x10}, newInt(16)},
496 {[]byte{0x13, 0x04, 't', 'e', 's', 't'}, newString("test")},
497 {[]byte{0x16, 0x04, 't', 'e', 's', 't'}, newString("test")},
498
499 {[]byte{0x13, 0x05, 't', 'e', 's', 't', '&'}, newString("test&")},
500 {[]byte{0x16, 0x04, 't', 'e', 's', 't'}, &RawValue{0, 22, false, []byte("test"), []byte("\x16\x04test")}},
501 {[]byte{0x04, 0x04, 1, 2, 3, 4}, &RawValue{0, 4, false, []byte{1, 2, 3, 4}, []byte{4, 4, 1, 2, 3, 4}}},
502 {[]byte{0x30, 0x03, 0x81, 0x01, 0x01}, &TestContextSpecificTags{1}},
503 {[]byte{0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, &TestContextSpecificTags2{1, 2}},
504 {[]byte{0x30, 0x03, 0x81, 0x01, '@'}, &TestContextSpecificTags3{"@"}},
505 {[]byte{0x01, 0x01, 0x00}, newBool(false)},
506 {[]byte{0x01, 0x01, 0xff}, newBool(true)},
507 {[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}},
508 {[]byte{0x30, 0x05, 0x02, 0x03, 0x12, 0x34, 0x56}, &TestBigInt{big.NewInt(0x123456)}},
509 {[]byte{0x30, 0x0b, 0x31, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &TestSet{Ints: []int{1, 2, 3}}},
510 {[]byte{0x12, 0x0b, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' '}, newString("0123456789 ")},
511 }
512
513 func TestUnmarshal(t *testing.T) {
514 for i, test := range unmarshalTestData {
515 pv := reflect.New(reflect.TypeOf(test.out).Elem())
516 val := pv.Interface()
517 _, err := Unmarshal(test.in, val)
518 if err != nil {
519 t.Errorf("Unmarshal failed at index %d %v", i, err)
520 }
521 if !reflect.DeepEqual(val, test.out) {
522 t.Errorf("#%d:\nhave %#v\nwant %#v", i, val, test.out)
523 }
524 }
525 }
526
527 func TestUnmarshalWithNilOrNonPointer(t *testing.T) {
528 tests := []struct {
529 b []byte
530 v any
531 want string
532 }{
533 {b: []byte{0x05, 0x00}, v: nil, want: "asn1: Unmarshal recipient value is nil"},
534 {b: []byte{0x05, 0x00}, v: RawValue{}, want: "asn1: Unmarshal recipient value is non-pointer asn1.RawValue"},
535 {b: []byte{0x05, 0x00}, v: (*RawValue)(nil), want: "asn1: Unmarshal recipient value is nil *asn1.RawValue"},
536 }
537
538 for _, test := range tests {
539 _, err := Unmarshal(test.b, test.v)
540 if err == nil {
541 t.Errorf("Unmarshal expecting error, got nil")
542 continue
543 }
544 if g, w := err.Error(), test.want; g != w {
545 t.Errorf("InvalidUnmarshalError mismatch\nGot: %q\nWant: %q", g, w)
546 }
547 }
548 }
549
550 type Certificate struct {
551 TBSCertificate TBSCertificate
552 SignatureAlgorithm AlgorithmIdentifier
553 SignatureValue BitString
554 }
555
556 type TBSCertificate struct {
557 Version int `asn1:"optional,explicit,default:0,tag:0"`
558 SerialNumber RawValue
559 SignatureAlgorithm AlgorithmIdentifier
560 Issuer RDNSequence
561 Validity Validity
562 Subject RDNSequence
563 PublicKey PublicKeyInfo
564 }
565
566 type AlgorithmIdentifier struct {
567 Algorithm ObjectIdentifier
568 }
569
570 type RDNSequence []RelativeDistinguishedNameSET
571
572 type RelativeDistinguishedNameSET []AttributeTypeAndValue
573
574 type AttributeTypeAndValue struct {
575 Type ObjectIdentifier
576 Value any
577 }
578
579 type Validity struct {
580 NotBefore, NotAfter time.Time
581 }
582
583 type PublicKeyInfo struct {
584 Algorithm AlgorithmIdentifier
585 PublicKey BitString
586 }
587
588 func TestCertificate(t *testing.T) {
589
590 var cert Certificate
591 if _, err := Unmarshal(derEncodedSelfSignedCertBytes, &cert); err != nil {
592 t.Errorf("Unmarshal failed: %v", err)
593 }
594 if !reflect.DeepEqual(cert, derEncodedSelfSignedCert) {
595 t.Errorf("Bad result:\ngot: %+v\nwant: %+v", cert, derEncodedSelfSignedCert)
596 }
597 }
598
599 func TestCertificateWithNUL(t *testing.T) {
600
601
602
603 var cert Certificate
604 if _, err := Unmarshal(derEncodedPaypalNULCertBytes, &cert); err == nil {
605 t.Error("Unmarshal succeeded, should not have")
606 }
607 }
608
609 type rawStructTest struct {
610 Raw RawContent
611 A int
612 }
613
614 func TestRawStructs(t *testing.T) {
615 var s rawStructTest
616 input := []byte{0x30, 0x03, 0x02, 0x01, 0x50}
617
618 rest, err := Unmarshal(input, &s)
619 if len(rest) != 0 {
620 t.Errorf("incomplete parse: %x", rest)
621 return
622 }
623 if err != nil {
624 t.Error(err)
625 return
626 }
627 if s.A != 0x50 {
628 t.Errorf("bad value for A: got %d want %d", s.A, 0x50)
629 }
630 if !bytes.Equal([]byte(s.Raw), input) {
631 t.Errorf("bad value for Raw: got %x want %x", s.Raw, input)
632 }
633 }
634
635 type oiEqualTest struct {
636 first ObjectIdentifier
637 second ObjectIdentifier
638 same bool
639 }
640
641 var oiEqualTests = []oiEqualTest{
642 {
643 ObjectIdentifier{1, 2, 3},
644 ObjectIdentifier{1, 2, 3},
645 true,
646 },
647 {
648 ObjectIdentifier{1},
649 ObjectIdentifier{1, 2, 3},
650 false,
651 },
652 {
653 ObjectIdentifier{1, 2, 3},
654 ObjectIdentifier{10, 11, 12},
655 false,
656 },
657 }
658
659 func TestObjectIdentifierEqual(t *testing.T) {
660 for _, o := range oiEqualTests {
661 if s := o.first.Equal(o.second); s != o.same {
662 t.Errorf("ObjectIdentifier.Equal: got: %t want: %t", s, o.same)
663 }
664 }
665 }
666
667 var derEncodedSelfSignedCert = Certificate{
668 TBSCertificate: TBSCertificate{
669 Version: 0,
670 SerialNumber: RawValue{Class: 0, Tag: 2, IsCompound: false, Bytes: []uint8{0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}, FullBytes: []byte{2, 9, 0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}},
671 SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}},
672 Issuer: RDNSequence{
673 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
674 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
675 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}},
676 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}},
677 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
678 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}},
679 },
680 Validity: Validity{
681 NotBefore: time.Date(2009, 10, 8, 00, 25, 53, 0, time.UTC),
682 NotAfter: time.Date(2010, 10, 8, 00, 25, 53, 0, time.UTC),
683 },
684 Subject: RDNSequence{
685 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
686 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
687 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}},
688 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}},
689 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
690 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}},
691 },
692 PublicKey: PublicKeyInfo{
693 Algorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}},
694 PublicKey: BitString{
695 Bytes: []uint8{
696 0x30, 0x48, 0x2, 0x41, 0x0, 0xcd, 0xb7,
697 0x63, 0x9c, 0x32, 0x78, 0xf0, 0x6, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42,
698 0x90, 0x2b, 0x59, 0x2d, 0x8c, 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4,
699 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea, 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2,
700 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88, 0x96, 0x57, 0x72, 0x2a, 0x4f,
701 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45, 0xdc, 0x8f, 0xde, 0xec,
702 0x35, 0x7d, 0x2, 0x3, 0x1, 0x0, 0x1,
703 },
704 BitLength: 592,
705 },
706 },
707 },
708 SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}},
709 SignatureValue: BitString{
710 Bytes: []uint8{
711 0xa6, 0x7b, 0x6, 0xec, 0x5e, 0xce,
712 0x92, 0x77, 0x2c, 0xa4, 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c,
713 0x7b, 0x45, 0x11, 0xcd, 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x4, 0x2, 0xdf, 0x2b,
714 0x99, 0x8b, 0xb9, 0xa4, 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8,
715 0xd9, 0x1e, 0xde, 0x14, 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa,
716 0xfa, 0x88, 0x21, 0x49, 0x4, 0x35,
717 },
718 BitLength: 512,
719 },
720 }
721
722 var derEncodedSelfSignedCertBytes = []byte{
723 0x30, 0x82, 0x02, 0x18, 0x30,
724 0x82, 0x01, 0xc2, 0x02, 0x09, 0x00, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c,
725 0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
726 0x05, 0x05, 0x00, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
727 0x04, 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
728 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
729 0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43,
730 0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
731 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
732 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31,
733 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c,
734 0x73, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
735 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
736 0x01, 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78,
737 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d,
738 0x30, 0x39, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35, 0x33, 0x5a,
739 0x17, 0x0d, 0x31, 0x30, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35,
740 0x33, 0x5a, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
741 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
742 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
743 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43, 0x69,
744 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18,
745 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
746 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x1a,
747 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c, 0x73,
748 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
749 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
750 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78, 0x61,
751 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06,
752 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
753 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xcd, 0xb7, 0x63, 0x9c, 0x32, 0x78,
754 0xf0, 0x06, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, 0x90, 0x2b, 0x59, 0x2d, 0x8c,
755 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4, 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea,
756 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2, 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88,
757 0x96, 0x57, 0x72, 0x2a, 0x4f, 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45,
758 0xdc, 0x8f, 0xde, 0xec, 0x35, 0x7d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d,
759 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
760 0x03, 0x41, 0x00, 0xa6, 0x7b, 0x06, 0xec, 0x5e, 0xce, 0x92, 0x77, 0x2c, 0xa4,
761 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, 0x7b, 0x45, 0x11, 0xcd,
762 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x04, 0x02, 0xdf, 0x2b, 0x99, 0x8b, 0xb9, 0xa4,
763 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8, 0xd9, 0x1e, 0xde, 0x14,
764 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa, 0xfa, 0x88, 0x21, 0x49,
765 0x04, 0x35,
766 }
767
768 var derEncodedPaypalNULCertBytes = []byte{
769 0x30, 0x82, 0x06, 0x44, 0x30,
770 0x82, 0x05, 0xad, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x00, 0xf0, 0x9b,
771 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
772 0x05, 0x00, 0x30, 0x82, 0x01, 0x12, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
773 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
774 0x04, 0x08, 0x13, 0x09, 0x42, 0x61, 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61,
775 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x42, 0x61,
776 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03,
777 0x55, 0x04, 0x0a, 0x13, 0x20, 0x49, 0x50, 0x53, 0x20, 0x43, 0x65, 0x72, 0x74,
778 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74,
779 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x73, 0x2e, 0x6c, 0x2e, 0x31, 0x2e,
780 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x25, 0x67, 0x65, 0x6e, 0x65,
781 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d,
782 0x20, 0x43, 0x2e, 0x49, 0x2e, 0x46, 0x2e, 0x20, 0x20, 0x42, 0x2d, 0x42, 0x36,
783 0x32, 0x32, 0x31, 0x30, 0x36, 0x39, 0x35, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03,
784 0x55, 0x04, 0x0b, 0x13, 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c,
785 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
786 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
787 0x69, 0x74, 0x79, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
788 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41,
789 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
790 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31,
791 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09,
792 0x01, 0x16, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70,
793 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39,
794 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a, 0x17, 0x0d,
795 0x31, 0x31, 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a,
796 0x30, 0x81, 0x94, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
797 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
798 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16,
799 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0d, 0x53, 0x61, 0x6e, 0x20,
800 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x31, 0x11, 0x30, 0x0f,
801 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
802 0x74, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b,
803 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x74, 0x31, 0x2f,
804 0x30, 0x2d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x26, 0x77, 0x77, 0x77, 0x2e,
805 0x70, 0x61, 0x79, 0x70, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x73, 0x73,
806 0x6c, 0x2e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
807 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x63, 0x63, 0x30, 0x81, 0x9f, 0x30, 0x0d,
808 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
809 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x69,
810 0xfa, 0x6f, 0x3a, 0x00, 0xb4, 0x21, 0x1b, 0xc8, 0xb1, 0x02, 0xd7, 0x3f, 0x19,
811 0xb2, 0xc4, 0x6d, 0xb4, 0x54, 0xf8, 0x8b, 0x8a, 0xcc, 0xdb, 0x72, 0xc2, 0x9e,
812 0x3c, 0x60, 0xb9, 0xc6, 0x91, 0x3d, 0x82, 0xb7, 0x7d, 0x99, 0xff, 0xd1, 0x29,
813 0x84, 0xc1, 0x73, 0x53, 0x9c, 0x82, 0xdd, 0xfc, 0x24, 0x8c, 0x77, 0xd5, 0x41,
814 0xf3, 0xe8, 0x1e, 0x42, 0xa1, 0xad, 0x2d, 0x9e, 0xff, 0x5b, 0x10, 0x26, 0xce,
815 0x9d, 0x57, 0x17, 0x73, 0x16, 0x23, 0x38, 0xc8, 0xd6, 0xf1, 0xba, 0xa3, 0x96,
816 0x5b, 0x16, 0x67, 0x4a, 0x4f, 0x73, 0x97, 0x3a, 0x4d, 0x14, 0xa4, 0xf4, 0xe2,
817 0x3f, 0x8b, 0x05, 0x83, 0x42, 0xd1, 0xd0, 0xdc, 0x2f, 0x7a, 0xe5, 0xb6, 0x10,
818 0xb2, 0x11, 0xc0, 0xdc, 0x21, 0x2a, 0x90, 0xff, 0xae, 0x97, 0x71, 0x5a, 0x49,
819 0x81, 0xac, 0x40, 0xf3, 0x3b, 0xb8, 0x59, 0xb2, 0x4f, 0x02, 0x03, 0x01, 0x00,
820 0x01, 0xa3, 0x82, 0x03, 0x21, 0x30, 0x82, 0x03, 0x1d, 0x30, 0x09, 0x06, 0x03,
821 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86,
822 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, 0x40,
823 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x03, 0xf8,
824 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08,
825 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1d, 0x06, 0x03, 0x55,
826 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x61, 0x8f, 0x61, 0x34, 0x43, 0x55, 0x14,
827 0x7f, 0x27, 0x09, 0xce, 0x4c, 0x8b, 0xea, 0x9b, 0x7b, 0x19, 0x25, 0xbc, 0x6e,
828 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
829 0x0e, 0x07, 0x60, 0xd4, 0x39, 0xc9, 0x1b, 0x5b, 0x5d, 0x90, 0x7b, 0x23, 0xc8,
830 0xd2, 0x34, 0x9d, 0x4a, 0x9a, 0x46, 0x39, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d,
831 0x11, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x1d, 0x12, 0x04,
832 0x15, 0x30, 0x13, 0x81, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40,
833 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x72, 0x06, 0x09,
834 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x65, 0x16, 0x63,
835 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
836 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e,
837 0x4f, 0x54, 0x20, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x44, 0x2e,
838 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x53, 0x65, 0x72, 0x76,
839 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
840 0x65, 0x20, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68,
841 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70,
842 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x2f, 0x06, 0x09, 0x60,
843 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x02, 0x04, 0x22, 0x16, 0x20, 0x68,
844 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70,
845 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61,
846 0x32, 0x30, 0x30, 0x32, 0x2f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
847 0x86, 0xf8, 0x42, 0x01, 0x04, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70,
848 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61,
849 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30,
850 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c,
851 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x46, 0x06, 0x09,
852 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x03, 0x04, 0x39, 0x16, 0x37,
853 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
854 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63,
855 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74,
856 0x69, 0x6f, 0x6e, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74,
857 0x6d, 0x6c, 0x3f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8,
858 0x42, 0x01, 0x07, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a,
859 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63,
860 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f,
861 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41,
862 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3f, 0x30, 0x41, 0x06, 0x09, 0x60, 0x86,
863 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x08, 0x04, 0x34, 0x16, 0x32, 0x68, 0x74,
864 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73,
865 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32,
866 0x30, 0x30, 0x32, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x4c, 0x41,
867 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x30, 0x81, 0x83, 0x06,
868 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x7c, 0x30, 0x7a, 0x30, 0x39, 0xa0, 0x37, 0xa0,
869 0x35, 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
870 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70,
871 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61,
872 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63,
873 0x72, 0x6c, 0x30, 0x3d, 0xa0, 0x3b, 0xa0, 0x39, 0x86, 0x37, 0x68, 0x74, 0x74,
874 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x69,
875 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63,
876 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30,
877 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c,
878 0x30, 0x32, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04,
879 0x26, 0x30, 0x24, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
880 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63,
881 0x73, 0x70, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
882 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
883 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x68, 0xee, 0x79, 0x97, 0x97, 0xdd, 0x3b,
884 0xef, 0x16, 0x6a, 0x06, 0xf2, 0x14, 0x9a, 0x6e, 0xcd, 0x9e, 0x12, 0xf7, 0xaa,
885 0x83, 0x10, 0xbd, 0xd1, 0x7c, 0x98, 0xfa, 0xc7, 0xae, 0xd4, 0x0e, 0x2c, 0x9e,
886 0x38, 0x05, 0x9d, 0x52, 0x60, 0xa9, 0x99, 0x0a, 0x81, 0xb4, 0x98, 0x90, 0x1d,
887 0xae, 0xbb, 0x4a, 0xd7, 0xb9, 0xdc, 0x88, 0x9e, 0x37, 0x78, 0x41, 0x5b, 0xf7,
888 0x82, 0xa5, 0xf2, 0xba, 0x41, 0x25, 0x5a, 0x90, 0x1a, 0x1e, 0x45, 0x38, 0xa1,
889 0x52, 0x58, 0x75, 0x94, 0x26, 0x44, 0xfb, 0x20, 0x07, 0xba, 0x44, 0xcc, 0xe5,
890 0x4a, 0x2d, 0x72, 0x3f, 0x98, 0x47, 0xf6, 0x26, 0xdc, 0x05, 0x46, 0x05, 0x07,
891 0x63, 0x21, 0xab, 0x46, 0x9b, 0x9c, 0x78, 0xd5, 0x54, 0x5b, 0x3d, 0x0c, 0x1e,
892 0xc8, 0x64, 0x8c, 0xb5, 0x50, 0x23, 0x82, 0x6f, 0xdb, 0xb8, 0x22, 0x1c, 0x43,
893 0x96, 0x07, 0xa8, 0xbb,
894 }
895
896 var stringSliceTestData = [][]string{
897 {"foo", "bar"},
898 {"foo", "\\bar"},
899 {"foo", "\"bar\""},
900 {"foo", "åäö"},
901 }
902
903 func TestStringSlice(t *testing.T) {
904 for _, test := range stringSliceTestData {
905 bs, err := Marshal(test)
906 if err != nil {
907 t.Error(err)
908 }
909
910 var res []string
911 _, err = Unmarshal(bs, &res)
912 if err != nil {
913 t.Error(err)
914 }
915
916 if fmt.Sprintf("%v", res) != fmt.Sprintf("%v", test) {
917 t.Errorf("incorrect marshal/unmarshal; %v != %v", res, test)
918 }
919 }
920 }
921
922 type explicitTaggedTimeTest struct {
923 Time time.Time `asn1:"explicit,tag:0"`
924 }
925
926 var explicitTaggedTimeTestData = []struct {
927 in []byte
928 out explicitTaggedTimeTest
929 }{
930 {[]byte{0x30, 0x11, 0xa0, 0xf, 0x17, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'},
931 explicitTaggedTimeTest{time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC)}},
932 {[]byte{0x30, 0x17, 0xa0, 0xf, 0x18, 0x13, '2', '0', '1', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '+', '0', '6', '0', '7'},
933 explicitTaggedTimeTest{time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))}},
934 }
935
936 func TestExplicitTaggedTime(t *testing.T) {
937
938
939 for i, test := range explicitTaggedTimeTestData {
940 var got explicitTaggedTimeTest
941 _, err := Unmarshal(test.in, &got)
942 if err != nil {
943 t.Errorf("Unmarshal failed at index %d %v", i, err)
944 }
945 if !got.Time.Equal(test.out.Time) {
946 t.Errorf("#%d: got %v, want %v", i, got.Time, test.out.Time)
947 }
948 }
949 }
950
951 type implicitTaggedTimeTest struct {
952 Time time.Time `asn1:"tag:24"`
953 }
954
955 func TestImplicitTaggedTime(t *testing.T) {
956
957
958
959
960 der := []byte{0x30, 0x0f, 0x80 | 24, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'}
961 var result implicitTaggedTimeTest
962 if _, err := Unmarshal(der, &result); err != nil {
963 t.Fatalf("Error while parsing: %s", err)
964 }
965 if expected := time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC); !result.Time.Equal(expected) {
966 t.Errorf("Wrong result. Got %v, want %v", result.Time, expected)
967 }
968 }
969
970 type truncatedExplicitTagTest struct {
971 Test int `asn1:"explicit,tag:0"`
972 }
973
974 func TestTruncatedExplicitTag(t *testing.T) {
975
976 der := []byte{
977 0x30,
978 0x02,
979 0xa0,
980 0x30,
981 }
982
983 var result truncatedExplicitTagTest
984 if _, err := Unmarshal(der, &result); err == nil {
985 t.Error("Unmarshal returned without error")
986 }
987 }
988
989 type invalidUTF8Test struct {
990 Str string `asn1:"utf8"`
991 }
992
993 func TestUnmarshalInvalidUTF8(t *testing.T) {
994 data := []byte("0\x05\f\x03a\xc9c")
995 var result invalidUTF8Test
996 _, err := Unmarshal(data, &result)
997
998 const expectedSubstring = "UTF"
999 if err == nil {
1000 t.Fatal("Successfully unmarshaled invalid UTF-8 data")
1001 } else if !strings.Contains(err.Error(), expectedSubstring) {
1002 t.Fatalf("Expected error to mention %q but error was %q", expectedSubstring, err.Error())
1003 }
1004 }
1005
1006 func TestMarshalNilValue(t *testing.T) {
1007 nilValueTestData := []any{
1008 nil,
1009 struct{ V any }{},
1010 }
1011 for i, test := range nilValueTestData {
1012 if _, err := Marshal(test); err == nil {
1013 t.Fatalf("#%d: successfully marshaled nil value", i)
1014 }
1015 }
1016 }
1017
1018 type unexported struct {
1019 X int
1020 y int
1021 }
1022
1023 type exported struct {
1024 X int
1025 Y int
1026 }
1027
1028 func TestUnexportedStructField(t *testing.T) {
1029 want := StructuralError{"struct contains unexported fields"}
1030
1031 _, err := Marshal(unexported{X: 5, y: 1})
1032 if err != want {
1033 t.Errorf("got %v, want %v", err, want)
1034 }
1035
1036 bs, err := Marshal(exported{X: 5, Y: 1})
1037 if err != nil {
1038 t.Fatal(err)
1039 }
1040 var u unexported
1041 _, err = Unmarshal(bs, &u)
1042 if err != want {
1043 t.Errorf("got %v, want %v", err, want)
1044 }
1045 }
1046
1047 func TestNull(t *testing.T) {
1048 marshaled, err := Marshal(NullRawValue)
1049 if err != nil {
1050 t.Fatal(err)
1051 }
1052 if !bytes.Equal(NullBytes, marshaled) {
1053 t.Errorf("Expected Marshal of NullRawValue to yield %x, got %x", NullBytes, marshaled)
1054 }
1055
1056 unmarshaled := RawValue{}
1057 if _, err := Unmarshal(NullBytes, &unmarshaled); err != nil {
1058 t.Fatal(err)
1059 }
1060
1061 unmarshaled.FullBytes = NullRawValue.FullBytes
1062 if len(unmarshaled.Bytes) == 0 {
1063
1064 unmarshaled.Bytes = NullRawValue.Bytes
1065 }
1066
1067 if !reflect.DeepEqual(NullRawValue, unmarshaled) {
1068 t.Errorf("Expected Unmarshal of NullBytes to yield %v, got %v", NullRawValue, unmarshaled)
1069 }
1070 }
1071
1072 func TestExplicitTagRawValueStruct(t *testing.T) {
1073 type foo struct {
1074 A RawValue `asn1:"optional,explicit,tag:5"`
1075 B []byte `asn1:"optional,explicit,tag:6"`
1076 }
1077 before := foo{B: []byte{1, 2, 3}}
1078 derBytes, err := Marshal(before)
1079 if err != nil {
1080 t.Fatal(err)
1081 }
1082
1083 var after foo
1084 if rest, err := Unmarshal(derBytes, &after); err != nil || len(rest) != 0 {
1085 t.Fatal(err)
1086 }
1087
1088 got := fmt.Sprintf("%#v", after)
1089 want := fmt.Sprintf("%#v", before)
1090 if got != want {
1091 t.Errorf("got %s, want %s (DER: %x)", got, want, derBytes)
1092 }
1093 }
1094
1095 func TestTaggedRawValue(t *testing.T) {
1096 type taggedRawValue struct {
1097 A RawValue `asn1:"tag:5"`
1098 }
1099 type untaggedRawValue struct {
1100 A RawValue
1101 }
1102 const isCompound = 0x20
1103 const tag = 5
1104
1105 tests := []struct {
1106 shouldMatch bool
1107 derBytes []byte
1108 }{
1109 {false, []byte{0x30, 3, TagInteger, 1, 1}},
1110 {true, []byte{0x30, 3, (ClassContextSpecific << 6) | tag, 1, 1}},
1111 {true, []byte{0x30, 3, (ClassContextSpecific << 6) | tag | isCompound, 1, 1}},
1112 {false, []byte{0x30, 3, (ClassApplication << 6) | tag | isCompound, 1, 1}},
1113 {false, []byte{0x30, 3, (ClassPrivate << 6) | tag | isCompound, 1, 1}},
1114 }
1115
1116 for i, test := range tests {
1117 var tagged taggedRawValue
1118 if _, err := Unmarshal(test.derBytes, &tagged); (err == nil) != test.shouldMatch {
1119 t.Errorf("#%d: unexpected result parsing %x: %s", i, test.derBytes, err)
1120 }
1121
1122
1123 var untagged untaggedRawValue
1124 if _, err := Unmarshal(test.derBytes, &untagged); err != nil {
1125 t.Errorf("#%d: unexpected failure parsing %x with untagged RawValue: %s", i, test.derBytes, err)
1126 }
1127 }
1128 }
1129
1130 var bmpStringTests = []struct {
1131 decoded string
1132 encodedHex string
1133 }{
1134 {"", "0000"},
1135
1136 {"Beavis", "0042006500610076006900730000"},
1137
1138 {"\u2115 - Double-struck N", "21150020002d00200044006f00750062006c0065002d00730074007200750063006b0020004e0000"},
1139 }
1140
1141 func TestBMPString(t *testing.T) {
1142 for i, test := range bmpStringTests {
1143 encoded, err := hex.DecodeString(test.encodedHex)
1144 if err != nil {
1145 t.Fatalf("#%d: failed to decode from hex string", i)
1146 }
1147
1148 decoded, err := parseBMPString(encoded)
1149
1150 if err != nil {
1151 t.Errorf("#%d: decoding output gave an error: %s", i, err)
1152 continue
1153 }
1154
1155 if decoded != test.decoded {
1156 t.Errorf("#%d: decoding output resulted in %q, but it should have been %q", i, decoded, test.decoded)
1157 continue
1158 }
1159 }
1160 }
1161
1162 func TestNonMinimalEncodedOID(t *testing.T) {
1163 h, err := hex.DecodeString("060a2a80864886f70d01010b")
1164 if err != nil {
1165 t.Fatalf("failed to decode from hex string: %s", err)
1166 }
1167 var oid ObjectIdentifier
1168 _, err = Unmarshal(h, &oid)
1169 if err == nil {
1170 t.Fatalf("accepted non-minimally encoded oid")
1171 }
1172 }
1173
1174 func BenchmarkObjectIdentifierString(b *testing.B) {
1175 oidPublicKeyRSA := ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
1176 for i := 0; i < b.N; i++ {
1177 _ = oidPublicKeyRSA.String()
1178 }
1179 }
1180
1181 func TestParsingMemoryConsumption(t *testing.T) {
1182
1183
1184
1185
1186 derBomb := make([]byte, 10_000_000)
1187 for i := range derBomb {
1188 derBomb[i] = 0x30
1189 }
1190 derBomb = append([]byte{0x30, 0x83, 0x98, 0x96, 0x80}, derBomb...)
1191
1192 var m runtime.MemStats
1193 runtime.GC()
1194 runtime.ReadMemStats(&m)
1195 memBefore := m.TotalAlloc
1196
1197 var out []struct {
1198 Id []int
1199 Critical bool `asn1:"optional"`
1200 Value []byte
1201 }
1202 _, err := Unmarshal(derBomb, &out)
1203 if !errors.As(err, &SyntaxError{}) {
1204 t.Fatalf("Incorrect error result: want (%v), but got (%v) instead", &SyntaxError{}, err)
1205 }
1206
1207 runtime.ReadMemStats(&m)
1208 memDiff := m.TotalAlloc - memBefore
1209
1210
1211
1212 if memDiff > 10<<21 {
1213 t.Errorf("Too much memory allocated while parsing DER: %v MiB", memDiff/1024/1024)
1214 }
1215 }
1216
View as plain text