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 {[]byte{0x14, 0x03, 0xbf, 0x61, 0x3f}, newString("¿a?")},
510 }
511
512 func TestUnmarshal(t *testing.T) {
513 for i, test := range unmarshalTestData {
514 pv := reflect.New(reflect.TypeOf(test.out).Elem())
515 val := pv.Interface()
516 _, err := Unmarshal(test.in, val)
517 if err != nil {
518 t.Errorf("Unmarshal failed at index %d %v", i, err)
519 }
520 if !reflect.DeepEqual(val, test.out) {
521 t.Errorf("#%d:\nhave %#v\nwant %#v", i, val, test.out)
522 }
523 }
524 }
525
526 func TestUnmarshalWithNilOrNonPointer(t *testing.T) {
527 tests := []struct {
528 b []byte
529 v any
530 want string
531 }{
532 {b: []byte{0x05, 0x00}, v: nil, want: "asn1: Unmarshal recipient value is nil"},
533 {b: []byte{0x05, 0x00}, v: RawValue{}, want: "asn1: Unmarshal recipient value is non-pointer asn1.RawValue"},
534 {b: []byte{0x05, 0x00}, v: (*RawValue)(nil), want: "asn1: Unmarshal recipient value is nil *asn1.RawValue"},
535 }
536
537 for _, test := range tests {
538 _, err := Unmarshal(test.b, test.v)
539 if err == nil {
540 t.Errorf("Unmarshal expecting error, got nil")
541 continue
542 }
543 if g, w := err.Error(), test.want; g != w {
544 t.Errorf("InvalidUnmarshalError mismatch\nGot: %q\nWant: %q", g, w)
545 }
546 }
547 }
548
549 type Certificate struct {
550 TBSCertificate TBSCertificate
551 SignatureAlgorithm AlgorithmIdentifier
552 SignatureValue BitString
553 }
554
555 type TBSCertificate struct {
556 Version int `asn1:"optional,explicit,default:0,tag:0"`
557 SerialNumber RawValue
558 SignatureAlgorithm AlgorithmIdentifier
559 Issuer RDNSequence
560 Validity Validity
561 Subject RDNSequence
562 PublicKey PublicKeyInfo
563 }
564
565 type AlgorithmIdentifier struct {
566 Algorithm ObjectIdentifier
567 }
568
569 type RDNSequence []RelativeDistinguishedNameSET
570
571 type RelativeDistinguishedNameSET []AttributeTypeAndValue
572
573 type AttributeTypeAndValue struct {
574 Type ObjectIdentifier
575 Value any
576 }
577
578 type Validity struct {
579 NotBefore, NotAfter time.Time
580 }
581
582 type PublicKeyInfo struct {
583 Algorithm AlgorithmIdentifier
584 PublicKey BitString
585 }
586
587 func TestCertificate(t *testing.T) {
588
589 var cert Certificate
590 if _, err := Unmarshal(derEncodedSelfSignedCertBytes, &cert); err != nil {
591 t.Errorf("Unmarshal failed: %v", err)
592 }
593 if !reflect.DeepEqual(cert, derEncodedSelfSignedCert) {
594 t.Errorf("Bad result:\ngot: %+v\nwant: %+v", cert, derEncodedSelfSignedCert)
595 }
596 }
597
598 func TestCertificateWithNUL(t *testing.T) {
599
600
601
602 var cert Certificate
603 if _, err := Unmarshal(derEncodedPaypalNULCertBytes, &cert); err == nil {
604 t.Error("Unmarshal succeeded, should not have")
605 }
606 }
607
608 type rawStructTest struct {
609 Raw RawContent
610 A int
611 }
612
613 func TestRawStructs(t *testing.T) {
614 var s rawStructTest
615 input := []byte{0x30, 0x03, 0x02, 0x01, 0x50}
616
617 rest, err := Unmarshal(input, &s)
618 if len(rest) != 0 {
619 t.Errorf("incomplete parse: %x", rest)
620 return
621 }
622 if err != nil {
623 t.Error(err)
624 return
625 }
626 if s.A != 0x50 {
627 t.Errorf("bad value for A: got %d want %d", s.A, 0x50)
628 }
629 if !bytes.Equal([]byte(s.Raw), input) {
630 t.Errorf("bad value for Raw: got %x want %x", s.Raw, input)
631 }
632 }
633
634 type oiEqualTest struct {
635 first ObjectIdentifier
636 second ObjectIdentifier
637 same bool
638 }
639
640 var oiEqualTests = []oiEqualTest{
641 {
642 ObjectIdentifier{1, 2, 3},
643 ObjectIdentifier{1, 2, 3},
644 true,
645 },
646 {
647 ObjectIdentifier{1},
648 ObjectIdentifier{1, 2, 3},
649 false,
650 },
651 {
652 ObjectIdentifier{1, 2, 3},
653 ObjectIdentifier{10, 11, 12},
654 false,
655 },
656 }
657
658 func TestObjectIdentifierEqual(t *testing.T) {
659 for _, o := range oiEqualTests {
660 if s := o.first.Equal(o.second); s != o.same {
661 t.Errorf("ObjectIdentifier.Equal: got: %t want: %t", s, o.same)
662 }
663 }
664 }
665
666 var derEncodedSelfSignedCert = Certificate{
667 TBSCertificate: TBSCertificate{
668 Version: 0,
669 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}},
670 SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}},
671 Issuer: RDNSequence{
672 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
673 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
674 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}},
675 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}},
676 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
677 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}},
678 },
679 Validity: Validity{
680 NotBefore: time.Date(2009, 10, 8, 00, 25, 53, 0, time.UTC),
681 NotAfter: time.Date(2010, 10, 8, 00, 25, 53, 0, time.UTC),
682 },
683 Subject: RDNSequence{
684 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
685 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
686 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}},
687 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}},
688 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
689 RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}},
690 },
691 PublicKey: PublicKeyInfo{
692 Algorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}},
693 PublicKey: BitString{
694 Bytes: []uint8{
695 0x30, 0x48, 0x2, 0x41, 0x0, 0xcd, 0xb7,
696 0x63, 0x9c, 0x32, 0x78, 0xf0, 0x6, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42,
697 0x90, 0x2b, 0x59, 0x2d, 0x8c, 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4,
698 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea, 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2,
699 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88, 0x96, 0x57, 0x72, 0x2a, 0x4f,
700 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45, 0xdc, 0x8f, 0xde, 0xec,
701 0x35, 0x7d, 0x2, 0x3, 0x1, 0x0, 0x1,
702 },
703 BitLength: 592,
704 },
705 },
706 },
707 SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}},
708 SignatureValue: BitString{
709 Bytes: []uint8{
710 0xa6, 0x7b, 0x6, 0xec, 0x5e, 0xce,
711 0x92, 0x77, 0x2c, 0xa4, 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c,
712 0x7b, 0x45, 0x11, 0xcd, 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x4, 0x2, 0xdf, 0x2b,
713 0x99, 0x8b, 0xb9, 0xa4, 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8,
714 0xd9, 0x1e, 0xde, 0x14, 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa,
715 0xfa, 0x88, 0x21, 0x49, 0x4, 0x35,
716 },
717 BitLength: 512,
718 },
719 }
720
721 var derEncodedSelfSignedCertBytes = []byte{
722 0x30, 0x82, 0x02, 0x18, 0x30,
723 0x82, 0x01, 0xc2, 0x02, 0x09, 0x00, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c,
724 0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
725 0x05, 0x05, 0x00, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
726 0x04, 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
727 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
728 0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43,
729 0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
730 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
731 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31,
732 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c,
733 0x73, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
734 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
735 0x01, 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78,
736 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d,
737 0x30, 0x39, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35, 0x33, 0x5a,
738 0x17, 0x0d, 0x31, 0x30, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35,
739 0x33, 0x5a, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
740 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
741 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
742 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43, 0x69,
743 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18,
744 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
745 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x1a,
746 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c, 0x73,
747 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
748 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
749 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78, 0x61,
750 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06,
751 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
752 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xcd, 0xb7, 0x63, 0x9c, 0x32, 0x78,
753 0xf0, 0x06, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, 0x90, 0x2b, 0x59, 0x2d, 0x8c,
754 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4, 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea,
755 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2, 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88,
756 0x96, 0x57, 0x72, 0x2a, 0x4f, 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45,
757 0xdc, 0x8f, 0xde, 0xec, 0x35, 0x7d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d,
758 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
759 0x03, 0x41, 0x00, 0xa6, 0x7b, 0x06, 0xec, 0x5e, 0xce, 0x92, 0x77, 0x2c, 0xa4,
760 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, 0x7b, 0x45, 0x11, 0xcd,
761 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x04, 0x02, 0xdf, 0x2b, 0x99, 0x8b, 0xb9, 0xa4,
762 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8, 0xd9, 0x1e, 0xde, 0x14,
763 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa, 0xfa, 0x88, 0x21, 0x49,
764 0x04, 0x35,
765 }
766
767 var derEncodedPaypalNULCertBytes = []byte{
768 0x30, 0x82, 0x06, 0x44, 0x30,
769 0x82, 0x05, 0xad, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x00, 0xf0, 0x9b,
770 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
771 0x05, 0x00, 0x30, 0x82, 0x01, 0x12, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
772 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
773 0x04, 0x08, 0x13, 0x09, 0x42, 0x61, 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61,
774 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x42, 0x61,
775 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03,
776 0x55, 0x04, 0x0a, 0x13, 0x20, 0x49, 0x50, 0x53, 0x20, 0x43, 0x65, 0x72, 0x74,
777 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74,
778 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x73, 0x2e, 0x6c, 0x2e, 0x31, 0x2e,
779 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x25, 0x67, 0x65, 0x6e, 0x65,
780 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d,
781 0x20, 0x43, 0x2e, 0x49, 0x2e, 0x46, 0x2e, 0x20, 0x20, 0x42, 0x2d, 0x42, 0x36,
782 0x32, 0x32, 0x31, 0x30, 0x36, 0x39, 0x35, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03,
783 0x55, 0x04, 0x0b, 0x13, 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c,
784 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
785 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
786 0x69, 0x74, 0x79, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
787 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41,
788 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
789 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31,
790 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09,
791 0x01, 0x16, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70,
792 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39,
793 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a, 0x17, 0x0d,
794 0x31, 0x31, 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a,
795 0x30, 0x81, 0x94, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
796 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
797 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16,
798 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0d, 0x53, 0x61, 0x6e, 0x20,
799 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x31, 0x11, 0x30, 0x0f,
800 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
801 0x74, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b,
802 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x74, 0x31, 0x2f,
803 0x30, 0x2d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x26, 0x77, 0x77, 0x77, 0x2e,
804 0x70, 0x61, 0x79, 0x70, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x73, 0x73,
805 0x6c, 0x2e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
806 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x63, 0x63, 0x30, 0x81, 0x9f, 0x30, 0x0d,
807 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
808 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x69,
809 0xfa, 0x6f, 0x3a, 0x00, 0xb4, 0x21, 0x1b, 0xc8, 0xb1, 0x02, 0xd7, 0x3f, 0x19,
810 0xb2, 0xc4, 0x6d, 0xb4, 0x54, 0xf8, 0x8b, 0x8a, 0xcc, 0xdb, 0x72, 0xc2, 0x9e,
811 0x3c, 0x60, 0xb9, 0xc6, 0x91, 0x3d, 0x82, 0xb7, 0x7d, 0x99, 0xff, 0xd1, 0x29,
812 0x84, 0xc1, 0x73, 0x53, 0x9c, 0x82, 0xdd, 0xfc, 0x24, 0x8c, 0x77, 0xd5, 0x41,
813 0xf3, 0xe8, 0x1e, 0x42, 0xa1, 0xad, 0x2d, 0x9e, 0xff, 0x5b, 0x10, 0x26, 0xce,
814 0x9d, 0x57, 0x17, 0x73, 0x16, 0x23, 0x38, 0xc8, 0xd6, 0xf1, 0xba, 0xa3, 0x96,
815 0x5b, 0x16, 0x67, 0x4a, 0x4f, 0x73, 0x97, 0x3a, 0x4d, 0x14, 0xa4, 0xf4, 0xe2,
816 0x3f, 0x8b, 0x05, 0x83, 0x42, 0xd1, 0xd0, 0xdc, 0x2f, 0x7a, 0xe5, 0xb6, 0x10,
817 0xb2, 0x11, 0xc0, 0xdc, 0x21, 0x2a, 0x90, 0xff, 0xae, 0x97, 0x71, 0x5a, 0x49,
818 0x81, 0xac, 0x40, 0xf3, 0x3b, 0xb8, 0x59, 0xb2, 0x4f, 0x02, 0x03, 0x01, 0x00,
819 0x01, 0xa3, 0x82, 0x03, 0x21, 0x30, 0x82, 0x03, 0x1d, 0x30, 0x09, 0x06, 0x03,
820 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86,
821 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, 0x40,
822 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x03, 0xf8,
823 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08,
824 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1d, 0x06, 0x03, 0x55,
825 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x61, 0x8f, 0x61, 0x34, 0x43, 0x55, 0x14,
826 0x7f, 0x27, 0x09, 0xce, 0x4c, 0x8b, 0xea, 0x9b, 0x7b, 0x19, 0x25, 0xbc, 0x6e,
827 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
828 0x0e, 0x07, 0x60, 0xd4, 0x39, 0xc9, 0x1b, 0x5b, 0x5d, 0x90, 0x7b, 0x23, 0xc8,
829 0xd2, 0x34, 0x9d, 0x4a, 0x9a, 0x46, 0x39, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d,
830 0x11, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x1d, 0x12, 0x04,
831 0x15, 0x30, 0x13, 0x81, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40,
832 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x72, 0x06, 0x09,
833 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x65, 0x16, 0x63,
834 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
835 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e,
836 0x4f, 0x54, 0x20, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x44, 0x2e,
837 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x53, 0x65, 0x72, 0x76,
838 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
839 0x65, 0x20, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68,
840 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70,
841 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x2f, 0x06, 0x09, 0x60,
842 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x02, 0x04, 0x22, 0x16, 0x20, 0x68,
843 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70,
844 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61,
845 0x32, 0x30, 0x30, 0x32, 0x2f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
846 0x86, 0xf8, 0x42, 0x01, 0x04, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70,
847 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61,
848 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30,
849 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c,
850 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x46, 0x06, 0x09,
851 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x03, 0x04, 0x39, 0x16, 0x37,
852 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
853 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63,
854 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74,
855 0x69, 0x6f, 0x6e, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74,
856 0x6d, 0x6c, 0x3f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8,
857 0x42, 0x01, 0x07, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a,
858 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63,
859 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f,
860 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41,
861 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3f, 0x30, 0x41, 0x06, 0x09, 0x60, 0x86,
862 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x08, 0x04, 0x34, 0x16, 0x32, 0x68, 0x74,
863 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73,
864 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32,
865 0x30, 0x30, 0x32, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x4c, 0x41,
866 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x30, 0x81, 0x83, 0x06,
867 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x7c, 0x30, 0x7a, 0x30, 0x39, 0xa0, 0x37, 0xa0,
868 0x35, 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
869 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70,
870 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61,
871 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63,
872 0x72, 0x6c, 0x30, 0x3d, 0xa0, 0x3b, 0xa0, 0x39, 0x86, 0x37, 0x68, 0x74, 0x74,
873 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x69,
874 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63,
875 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30,
876 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c,
877 0x30, 0x32, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04,
878 0x26, 0x30, 0x24, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
879 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63,
880 0x73, 0x70, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
881 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
882 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x68, 0xee, 0x79, 0x97, 0x97, 0xdd, 0x3b,
883 0xef, 0x16, 0x6a, 0x06, 0xf2, 0x14, 0x9a, 0x6e, 0xcd, 0x9e, 0x12, 0xf7, 0xaa,
884 0x83, 0x10, 0xbd, 0xd1, 0x7c, 0x98, 0xfa, 0xc7, 0xae, 0xd4, 0x0e, 0x2c, 0x9e,
885 0x38, 0x05, 0x9d, 0x52, 0x60, 0xa9, 0x99, 0x0a, 0x81, 0xb4, 0x98, 0x90, 0x1d,
886 0xae, 0xbb, 0x4a, 0xd7, 0xb9, 0xdc, 0x88, 0x9e, 0x37, 0x78, 0x41, 0x5b, 0xf7,
887 0x82, 0xa5, 0xf2, 0xba, 0x41, 0x25, 0x5a, 0x90, 0x1a, 0x1e, 0x45, 0x38, 0xa1,
888 0x52, 0x58, 0x75, 0x94, 0x26, 0x44, 0xfb, 0x20, 0x07, 0xba, 0x44, 0xcc, 0xe5,
889 0x4a, 0x2d, 0x72, 0x3f, 0x98, 0x47, 0xf6, 0x26, 0xdc, 0x05, 0x46, 0x05, 0x07,
890 0x63, 0x21, 0xab, 0x46, 0x9b, 0x9c, 0x78, 0xd5, 0x54, 0x5b, 0x3d, 0x0c, 0x1e,
891 0xc8, 0x64, 0x8c, 0xb5, 0x50, 0x23, 0x82, 0x6f, 0xdb, 0xb8, 0x22, 0x1c, 0x43,
892 0x96, 0x07, 0xa8, 0xbb,
893 }
894
895 var stringSliceTestData = [][]string{
896 {"foo", "bar"},
897 {"foo", "\\bar"},
898 {"foo", "\"bar\""},
899 {"foo", "åäö"},
900 }
901
902 func TestStringSlice(t *testing.T) {
903 for _, test := range stringSliceTestData {
904 bs, err := Marshal(test)
905 if err != nil {
906 t.Error(err)
907 }
908
909 var res []string
910 _, err = Unmarshal(bs, &res)
911 if err != nil {
912 t.Error(err)
913 }
914
915 if fmt.Sprintf("%v", res) != fmt.Sprintf("%v", test) {
916 t.Errorf("incorrect marshal/unmarshal; %v != %v", res, test)
917 }
918 }
919 }
920
921 type explicitTaggedTimeTest struct {
922 Time time.Time `asn1:"explicit,tag:0"`
923 }
924
925 var explicitTaggedTimeTestData = []struct {
926 in []byte
927 out explicitTaggedTimeTest
928 }{
929 {[]byte{0x30, 0x11, 0xa0, 0xf, 0x17, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'},
930 explicitTaggedTimeTest{time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC)}},
931 {[]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'},
932 explicitTaggedTimeTest{time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))}},
933 }
934
935 func TestExplicitTaggedTime(t *testing.T) {
936
937
938 for i, test := range explicitTaggedTimeTestData {
939 var got explicitTaggedTimeTest
940 _, err := Unmarshal(test.in, &got)
941 if err != nil {
942 t.Errorf("Unmarshal failed at index %d %v", i, err)
943 }
944 if !got.Time.Equal(test.out.Time) {
945 t.Errorf("#%d: got %v, want %v", i, got.Time, test.out.Time)
946 }
947 }
948 }
949
950 type implicitTaggedTimeTest struct {
951 Time time.Time `asn1:"tag:24"`
952 }
953
954 func TestImplicitTaggedTime(t *testing.T) {
955
956
957
958
959 der := []byte{0x30, 0x0f, 0x80 | 24, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'}
960 var result implicitTaggedTimeTest
961 if _, err := Unmarshal(der, &result); err != nil {
962 t.Fatalf("Error while parsing: %s", err)
963 }
964 if expected := time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC); !result.Time.Equal(expected) {
965 t.Errorf("Wrong result. Got %v, want %v", result.Time, expected)
966 }
967 }
968
969 type truncatedExplicitTagTest struct {
970 Test int `asn1:"explicit,tag:0"`
971 }
972
973 func TestTruncatedExplicitTag(t *testing.T) {
974
975 der := []byte{
976 0x30,
977 0x02,
978 0xa0,
979 0x30,
980 }
981
982 var result truncatedExplicitTagTest
983 if _, err := Unmarshal(der, &result); err == nil {
984 t.Error("Unmarshal returned without error")
985 }
986 }
987
988 type invalidUTF8Test struct {
989 Str string `asn1:"utf8"`
990 }
991
992 func TestUnmarshalInvalidUTF8(t *testing.T) {
993 data := []byte("0\x05\f\x03a\xc9c")
994 var result invalidUTF8Test
995 _, err := Unmarshal(data, &result)
996
997 const expectedSubstring = "UTF"
998 if err == nil {
999 t.Fatal("Successfully unmarshaled invalid UTF-8 data")
1000 } else if !strings.Contains(err.Error(), expectedSubstring) {
1001 t.Fatalf("Expected error to mention %q but error was %q", expectedSubstring, err.Error())
1002 }
1003 }
1004
1005 func TestMarshalNilValue(t *testing.T) {
1006 nilValueTestData := []any{
1007 nil,
1008 struct{ V any }{},
1009 }
1010 for i, test := range nilValueTestData {
1011 if _, err := Marshal(test); err == nil {
1012 t.Fatalf("#%d: successfully marshaled nil value", i)
1013 }
1014 }
1015 }
1016
1017 type unexported struct {
1018 X int
1019 y int
1020 }
1021
1022 type exported struct {
1023 X int
1024 Y int
1025 }
1026
1027 func TestUnexportedStructField(t *testing.T) {
1028 want := StructuralError{"struct contains unexported fields"}
1029
1030 _, err := Marshal(unexported{X: 5, y: 1})
1031 if err != want {
1032 t.Errorf("got %v, want %v", err, want)
1033 }
1034
1035 bs, err := Marshal(exported{X: 5, Y: 1})
1036 if err != nil {
1037 t.Fatal(err)
1038 }
1039 var u unexported
1040 _, err = Unmarshal(bs, &u)
1041 if err != want {
1042 t.Errorf("got %v, want %v", err, want)
1043 }
1044 }
1045
1046 func TestNull(t *testing.T) {
1047 marshaled, err := Marshal(NullRawValue)
1048 if err != nil {
1049 t.Fatal(err)
1050 }
1051 if !bytes.Equal(NullBytes, marshaled) {
1052 t.Errorf("Expected Marshal of NullRawValue to yield %x, got %x", NullBytes, marshaled)
1053 }
1054
1055 unmarshaled := RawValue{}
1056 if _, err := Unmarshal(NullBytes, &unmarshaled); err != nil {
1057 t.Fatal(err)
1058 }
1059
1060 unmarshaled.FullBytes = NullRawValue.FullBytes
1061 if len(unmarshaled.Bytes) == 0 {
1062
1063 unmarshaled.Bytes = NullRawValue.Bytes
1064 }
1065
1066 if !reflect.DeepEqual(NullRawValue, unmarshaled) {
1067 t.Errorf("Expected Unmarshal of NullBytes to yield %v, got %v", NullRawValue, unmarshaled)
1068 }
1069 }
1070
1071 func TestExplicitTagRawValueStruct(t *testing.T) {
1072 type foo struct {
1073 A RawValue `asn1:"optional,explicit,tag:5"`
1074 B []byte `asn1:"optional,explicit,tag:6"`
1075 }
1076 before := foo{B: []byte{1, 2, 3}}
1077 derBytes, err := Marshal(before)
1078 if err != nil {
1079 t.Fatal(err)
1080 }
1081
1082 var after foo
1083 if rest, err := Unmarshal(derBytes, &after); err != nil || len(rest) != 0 {
1084 t.Fatal(err)
1085 }
1086
1087 got := fmt.Sprintf("%#v", after)
1088 want := fmt.Sprintf("%#v", before)
1089 if got != want {
1090 t.Errorf("got %s, want %s (DER: %x)", got, want, derBytes)
1091 }
1092 }
1093
1094 func TestTaggedRawValue(t *testing.T) {
1095 type taggedRawValue struct {
1096 A RawValue `asn1:"tag:5"`
1097 }
1098 type untaggedRawValue struct {
1099 A RawValue
1100 }
1101 const isCompound = 0x20
1102 const tag = 5
1103
1104 tests := []struct {
1105 shouldMatch bool
1106 derBytes []byte
1107 }{
1108 {false, []byte{0x30, 3, TagInteger, 1, 1}},
1109 {true, []byte{0x30, 3, (ClassContextSpecific << 6) | tag, 1, 1}},
1110 {true, []byte{0x30, 3, (ClassContextSpecific << 6) | tag | isCompound, 1, 1}},
1111 {false, []byte{0x30, 3, (ClassApplication << 6) | tag | isCompound, 1, 1}},
1112 {false, []byte{0x30, 3, (ClassPrivate << 6) | tag | isCompound, 1, 1}},
1113 }
1114
1115 for i, test := range tests {
1116 var tagged taggedRawValue
1117 if _, err := Unmarshal(test.derBytes, &tagged); (err == nil) != test.shouldMatch {
1118 t.Errorf("#%d: unexpected result parsing %x: %s", i, test.derBytes, err)
1119 }
1120
1121
1122 var untagged untaggedRawValue
1123 if _, err := Unmarshal(test.derBytes, &untagged); err != nil {
1124 t.Errorf("#%d: unexpected failure parsing %x with untagged RawValue: %s", i, test.derBytes, err)
1125 }
1126 }
1127 }
1128
1129 var bmpStringTests = []struct {
1130 name string
1131 decoded string
1132 encodedHex string
1133 invalid bool
1134 }{
1135 {"empty string", "", "0000", false},
1136
1137 {"rfc7292 example", "Beavis", "0042006500610076006900730000", false},
1138
1139 {"letterlike symbols", "\u2115 - Double-struck N", "21150020002d00200044006f00750062006c0065002d00730074007200750063006b0020004e0000", false},
1140 {"invalid length", "", "ff", true},
1141 {"invalid surrogate", "", "5051d801", true},
1142 {"invalid noncharacter 0xfdd1", "", "5051fdd1", true},
1143 {"invalid noncharacter 0xffff", "", "5051ffff", true},
1144 {"invalid noncharacter 0xfffe", "", "5051fffe", true},
1145 }
1146
1147 func TestBMPString(t *testing.T) {
1148 for _, test := range bmpStringTests {
1149 t.Run(test.name, func(t *testing.T) {
1150 encoded, err := hex.DecodeString(test.encodedHex)
1151 if err != nil {
1152 t.Fatalf("failed to decode from hex string: %s", err)
1153 }
1154
1155 decoded, err := parseBMPString(encoded)
1156
1157 if err != nil && !test.invalid {
1158 t.Errorf("parseBMPString failed: %s", err)
1159 } else if test.invalid && err == nil {
1160 t.Error("parseBMPString didn't fail as expected")
1161 }
1162
1163 if decoded != test.decoded {
1164 t.Errorf("parseBMPString(%q): got %q, want %q", encoded, decoded, test.decoded)
1165 }
1166 })
1167 }
1168 }
1169
1170 func TestNonMinimalEncodedOID(t *testing.T) {
1171 h, err := hex.DecodeString("060a2a80864886f70d01010b")
1172 if err != nil {
1173 t.Fatalf("failed to decode from hex string: %s", err)
1174 }
1175 var oid ObjectIdentifier
1176 _, err = Unmarshal(h, &oid)
1177 if err == nil {
1178 t.Fatalf("accepted non-minimally encoded oid")
1179 }
1180 }
1181
1182 func BenchmarkObjectIdentifierString(b *testing.B) {
1183 oidPublicKeyRSA := ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
1184 for i := 0; i < b.N; i++ {
1185 _ = oidPublicKeyRSA.String()
1186 }
1187 }
1188
1189 func TestImplicitTypeRoundtrip(t *testing.T) {
1190 type tagged struct {
1191 IA5 string `asn1:"tag:1,ia5"`
1192 Printable string `asn1:"tag:2,printable"`
1193 UTF8 string `asn1:"tag:3,utf8"`
1194 Numeric string `asn1:"tag:4,numeric"`
1195 UTC time.Time `asn1:"tag:5,utc"`
1196 Generalized time.Time `asn1:"tag:6,generalized"`
1197 }
1198 a := tagged{
1199 IA5: "ia5",
1200 Printable: "printable",
1201 UTF8: "utf8",
1202 Numeric: "123 456",
1203 UTC: time.Now().UTC().Truncate(time.Second),
1204 Generalized: time.Now().UTC().Truncate(time.Second),
1205 }
1206 enc, err := Marshal(a)
1207 if err != nil {
1208 t.Fatalf("Marshal failed: %s", err)
1209 }
1210 var b tagged
1211 if _, err := Unmarshal(enc, &b); err != nil {
1212 t.Fatalf("Unmarshal failed: %s", err)
1213 }
1214
1215 if !reflect.DeepEqual(a, b) {
1216 t.Fatalf("Unexpected diff after roundtripping struct\na: %#v\nb: %#v", a, b)
1217 }
1218 }
1219
View as plain text