1
2
3
4
5 package asn1
6
7 import (
8 "bytes"
9 "encoding/hex"
10 "math/big"
11 "reflect"
12 "slices"
13 "strings"
14 "testing"
15 "time"
16 )
17
18 type intStruct struct {
19 A int
20 }
21
22 type twoIntStruct struct {
23 A int
24 B int
25 }
26
27 type bigIntStruct struct {
28 A *big.Int
29 }
30
31 type nestedStruct struct {
32 A intStruct
33 }
34
35 type rawContentsStruct struct {
36 Raw RawContent
37 A int
38 }
39
40 type implicitTagTest struct {
41 A int `asn1:"implicit,tag:5"`
42 }
43
44 type explicitTagTest struct {
45 A int `asn1:"explicit,tag:5"`
46 }
47
48 type flagTest struct {
49 A Flag `asn1:"tag:0,optional"`
50 }
51
52 type generalizedTimeTest struct {
53 A time.Time `asn1:"generalized"`
54 }
55
56 type ia5StringTest struct {
57 A string `asn1:"ia5"`
58 }
59
60 type printableStringTest struct {
61 A string `asn1:"printable"`
62 }
63
64 type genericStringTest struct {
65 A string
66 }
67
68 type optionalRawValueTest struct {
69 A RawValue `asn1:"optional"`
70 }
71
72 type omitEmptyTest struct {
73 A []string `asn1:"omitempty"`
74 }
75
76 type defaultTest struct {
77 A int `asn1:"optional,default:1"`
78 }
79
80 type applicationTest struct {
81 A int `asn1:"application,tag:0"`
82 B int `asn1:"application,tag:1,explicit"`
83 }
84
85 type privateTest struct {
86 A int `asn1:"private,tag:0"`
87 B int `asn1:"private,tag:1,explicit"`
88 C int `asn1:"private,tag:31"`
89 D int `asn1:"private,tag:128"`
90 }
91
92 type numericStringTest struct {
93 A string `asn1:"numeric"`
94 }
95
96 type testSET []int
97
98 var PST = time.FixedZone("PST", -8*60*60)
99
100 type marshalTest struct {
101 in any
102 out string
103 }
104
105 func farFuture() time.Time {
106 t, err := time.Parse(time.RFC3339, "2100-04-05T12:01:01Z")
107 if err != nil {
108 panic(err)
109 }
110 return t
111 }
112
113 var marshalTests = []marshalTest{
114 {10, "02010a"},
115 {127, "02017f"},
116 {128, "02020080"},
117 {-128, "020180"},
118 {-129, "0202ff7f"},
119 {intStruct{64}, "3003020140"},
120 {bigIntStruct{big.NewInt(0x123456)}, "30050203123456"},
121 {twoIntStruct{64, 65}, "3006020140020141"},
122 {nestedStruct{intStruct{127}}, "3005300302017f"},
123 {[]byte{1, 2, 3}, "0403010203"},
124 {implicitTagTest{64}, "3003850140"},
125 {explicitTagTest{64}, "3005a503020140"},
126 {flagTest{true}, "30028000"},
127 {flagTest{false}, "3000"},
128 {time.Unix(0, 0).UTC(), "170d3730303130313030303030305a"},
129 {time.Unix(1258325776, 0).UTC(), "170d3039313131353232353631365a"},
130 {time.Unix(1258325776, 0).In(PST), "17113039313131353134353631362d30383030"},
131 {farFuture(), "180f32313030303430353132303130315a"},
132 {generalizedTimeTest{time.Unix(1258325776, 0).UTC()}, "3011180f32303039313131353232353631365a"},
133 {BitString{[]byte{0x80}, 1}, "03020780"},
134 {BitString{[]byte{0x81, 0xf0}, 12}, "03030481f0"},
135 {ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"},
136 {ObjectIdentifier([]int{1, 2, 840, 133549, 1, 1, 5}), "06092a864888932d010105"},
137 {ObjectIdentifier([]int{2, 100, 3}), "0603813403"},
138 {"test", "130474657374"},
139 {
140 "" +
141 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
142 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
143 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
144 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
145 "137f" +
146 "7878787878787878787878787878787878787878787878787878787878787878" +
147 "7878787878787878787878787878787878787878787878787878787878787878" +
148 "7878787878787878787878787878787878787878787878787878787878787878" +
149 "78787878787878787878787878787878787878787878787878787878787878",
150 },
151 {
152 "" +
153 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
154 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
155 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
156 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
157 "138180" +
158 "7878787878787878787878787878787878787878787878787878787878787878" +
159 "7878787878787878787878787878787878787878787878787878787878787878" +
160 "7878787878787878787878787878787878787878787878787878787878787878" +
161 "7878787878787878787878787878787878787878787878787878787878787878",
162 },
163 {ia5StringTest{"test"}, "3006160474657374"},
164 {optionalRawValueTest{}, "3000"},
165 {printableStringTest{"test"}, "3006130474657374"},
166 {printableStringTest{"test*"}, "30071305746573742a"},
167 {genericStringTest{"test"}, "3006130474657374"},
168 {genericStringTest{"test*"}, "30070c05746573742a"},
169 {genericStringTest{"test&"}, "30070c057465737426"},
170 {rawContentsStruct{nil, 64}, "3003020140"},
171 {rawContentsStruct{[]byte{0x30, 3, 1, 2, 3}, 64}, "3003010203"},
172 {RawValue{Tag: 1, Class: 2, IsCompound: false, Bytes: []byte{1, 2, 3}}, "8103010203"},
173 {testSET([]int{10}), "310302010a"},
174 {omitEmptyTest{[]string{}}, "3000"},
175 {omitEmptyTest{[]string{"1"}}, "30053003130131"},
176 {"Σ", "0c02cea3"},
177 {defaultTest{0}, "3003020100"},
178 {defaultTest{1}, "3000"},
179 {defaultTest{2}, "3003020102"},
180 {applicationTest{1, 2}, "30084001016103020102"},
181 {privateTest{1, 2, 3, 4}, "3011c00101e103020102df1f0103df81000104"},
182 {numericStringTest{"1 9"}, "30051203312039"},
183 }
184
185 func TestMarshal(t *testing.T) {
186 for i, test := range marshalTests {
187 data, err := Marshal(test.in)
188 if err != nil {
189 t.Errorf("#%d failed: %s", i, err)
190 }
191 out, _ := hex.DecodeString(test.out)
192 if !bytes.Equal(out, data) {
193 t.Errorf("#%d got: %x want %x\n\t%q\n\t%q", i, data, out, data, out)
194
195 }
196 }
197 }
198
199 type marshalWithParamsTest struct {
200 in any
201 params string
202 out string
203 }
204
205 var marshalWithParamsTests = []marshalWithParamsTest{
206 {intStruct{10}, "set", "310302010a"},
207 {intStruct{10}, "application", "600302010a"},
208 {intStruct{10}, "private", "e00302010a"},
209 }
210
211 func TestMarshalWithParams(t *testing.T) {
212 for i, test := range marshalWithParamsTests {
213 data, err := MarshalWithParams(test.in, test.params)
214 if err != nil {
215 t.Errorf("#%d failed: %s", i, err)
216 }
217 out, _ := hex.DecodeString(test.out)
218 if !bytes.Equal(out, data) {
219 t.Errorf("#%d got: %x want %x\n\t%q\n\t%q", i, data, out, data, out)
220
221 }
222 }
223 }
224
225 type marshalErrTest struct {
226 in any
227 err string
228 }
229
230 var marshalErrTests = []marshalErrTest{
231 {bigIntStruct{nil}, "empty integer"},
232 {numericStringTest{"a"}, "invalid character"},
233 {ia5StringTest{"\xb0"}, "invalid character"},
234 {printableStringTest{"!"}, "invalid character"},
235 }
236
237 func TestMarshalError(t *testing.T) {
238 for i, test := range marshalErrTests {
239 _, err := Marshal(test.in)
240 if err == nil {
241 t.Errorf("#%d should fail, but success", i)
242 continue
243 }
244
245 if !strings.Contains(err.Error(), test.err) {
246 t.Errorf("#%d got: %v want %v", i, err, test.err)
247 }
248 }
249 }
250
251 func TestInvalidUTF8(t *testing.T) {
252 _, err := Marshal(string([]byte{0xff, 0xff}))
253 if err == nil {
254 t.Errorf("invalid UTF8 string was accepted")
255 }
256 }
257
258 func TestMarshalOID(t *testing.T) {
259 var marshalTestsOID = []marshalTest{
260 {[]byte("\x06\x01\x30"), "0403060130"},
261
262 {[]byte("\x06\x010"), "0403060130"},
263 {ObjectIdentifier([]int{2, 999, 3}), "0603883703"},
264 {ObjectIdentifier([]int{0, 0}), "060100"},
265 }
266 for i, test := range marshalTestsOID {
267 data, err := Marshal(test.in)
268 if err != nil {
269 t.Errorf("#%d failed: %s", i, err)
270 }
271 out, _ := hex.DecodeString(test.out)
272 if !bytes.Equal(out, data) {
273 t.Errorf("#%d got: %x want %x\n\t%q\n\t%q", i, data, out, data, out)
274 }
275 }
276 }
277
278 func TestIssue11130(t *testing.T) {
279 data := []byte("\x06\x010")
280 var v any
281
282 _, err := Unmarshal(data, &v)
283 if err != nil {
284 t.Errorf("%v", err)
285 return
286 }
287 if reflect.TypeOf(v).String() != reflect.TypeOf(ObjectIdentifier{}).String() {
288 t.Errorf("marshal OID returned an invalid type")
289 return
290 }
291
292 data1, err := Marshal(v)
293 if err != nil {
294 t.Errorf("%v", err)
295 return
296 }
297
298 if !bytes.Equal(data, data1) {
299 t.Errorf("got: %q, want: %q \n", data1, data)
300 return
301 }
302
303 var v1 any
304 _, err = Unmarshal(data1, &v1)
305 if err != nil {
306 t.Errorf("%v", err)
307 return
308 }
309 if !reflect.DeepEqual(v, v1) {
310 t.Errorf("got: %#v data=%q, want : %#v data=%q\n ", v1, data1, v, data)
311 }
312 }
313
314 func TestIssue68241(t *testing.T) {
315 for i, want := range []any{false, true} {
316 data, err := Marshal(want)
317 if err != nil {
318 t.Errorf("cannot Marshal: %v", err)
319 return
320 }
321
322 var got any
323 _, err = Unmarshal(data, &got)
324 if err != nil {
325 t.Errorf("cannot Unmarshal: %v", err)
326 return
327 }
328 if !reflect.DeepEqual(got, want) {
329 t.Errorf("#%d Unmarshal, got: %v, want: %v", i, got, want)
330 }
331 }
332 }
333
334 func BenchmarkMarshal(b *testing.B) {
335 b.ReportAllocs()
336
337 for i := 0; i < b.N; i++ {
338 for _, test := range marshalTests {
339 Marshal(test.in)
340 }
341 }
342 }
343
344 func TestSetEncoder(t *testing.T) {
345 testStruct := struct {
346 Strings []string `asn1:"set"`
347 }{
348 Strings: []string{"a", "aa", "b", "bb", "c", "cc"},
349 }
350
351
352
353
354 output, err := Marshal(testStruct)
355 if err != nil {
356 t.Errorf("%v", err)
357 }
358
359 expectedOrder := []string{"a", "b", "c", "aa", "bb", "cc"}
360 var resultStruct struct {
361 Strings []string `asn1:"set"`
362 }
363 rest, err := Unmarshal(output, &resultStruct)
364 if err != nil {
365 t.Errorf("%v", err)
366 }
367 if len(rest) != 0 {
368 t.Error("Unmarshal returned extra garbage")
369 }
370 if !slices.Equal(expectedOrder, resultStruct.Strings) {
371 t.Errorf("Unexpected SET content. got: %s, want: %s", resultStruct.Strings, expectedOrder)
372 }
373 }
374
375 func TestSetEncoderSETSliceSuffix(t *testing.T) {
376 type testSetSET []string
377 testSet := testSetSET{"a", "aa", "b", "bb", "c", "cc"}
378
379
380
381
382 output, err := Marshal(testSet)
383 if err != nil {
384 t.Errorf("%v", err)
385 }
386
387 expectedOrder := testSetSET{"a", "b", "c", "aa", "bb", "cc"}
388 var resultSet testSetSET
389 rest, err := Unmarshal(output, &resultSet)
390 if err != nil {
391 t.Errorf("%v", err)
392 }
393 if len(rest) != 0 {
394 t.Error("Unmarshal returned extra garbage")
395 }
396 if !reflect.DeepEqual(expectedOrder, resultSet) {
397 t.Errorf("Unexpected SET content. got: %s, want: %s", resultSet, expectedOrder)
398 }
399 }
400
401 func BenchmarkUnmarshal(b *testing.B) {
402 b.ReportAllocs()
403
404 type testCase struct {
405 in []byte
406 out any
407 }
408 var testData []testCase
409 for _, test := range unmarshalTestData {
410 pv := reflect.New(reflect.TypeOf(test.out).Elem())
411 inCopy := make([]byte, len(test.in))
412 copy(inCopy, test.in)
413 outCopy := pv.Interface()
414
415 testData = append(testData, testCase{
416 in: inCopy,
417 out: outCopy,
418 })
419 }
420
421 b.ResetTimer()
422 for i := 0; i < b.N; i++ {
423 for _, testCase := range testData {
424 _, _ = Unmarshal(testCase.in, testCase.out)
425 }
426 }
427 }
428
View as plain text