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