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