├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── asn1.go ├── asn1_test.go ├── context.go ├── decode.go ├── encode.go ├── example_test.go ├── gen_readme.sh ├── options.go ├── raw.go ├── sort.go └── types.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Vim swap files 2 | .*.swp 3 | 4 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 5 | *.o 6 | *.a 7 | *.so 8 | 9 | # Folders 10 | _obj 11 | _test 12 | 13 | # Architecture specific extensions/prefixes 14 | *.[568vq] 15 | [568vq].out 16 | 17 | *.cgo1.go 18 | *.cgo2.c 19 | _cgo_defun.c 20 | _cgo_gotypes.go 21 | _cgo_export.* 22 | 23 | _testmain.go 24 | 25 | *.exe 26 | *.test 27 | *.prof 28 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.5 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 PromonLogicalis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # WARNING 4 | 5 | ## This repo has been archived! 6 | 7 | NO further developement will be made in the foreseen future. 8 | 9 | --- 10 | 11 | 12 | [![Build Status](https://travis-ci.org/PromonLogicalis/asn1.svg?branch=master)](https://travis-ci.org/PromonLogicalis/asn1) [![Go Report Card](https://goreportcard.com/badge/github.com/PromonLogicalis/asn1)](https://goreportcard.com/report/github.com/PromonLogicalis/asn1) [![GoDoc](https://godoc.org/github.com/PromonLogicalis/asn1?status.svg)](https://godoc.org/github.com/PromonLogicalis/asn1) 13 | # asn1 14 | -- 15 | import "github.com/PromonLogicalis/asn1" 16 | 17 | Package asn1 implements encoding and decoding of ASN.1 data structures using 18 | both Basic Encoding Rules (BER) or its subset, the Distinguished Encoding Rules 19 | (BER). 20 | 21 | This package is highly inspired by the Go standard package "encoding/asn1" while 22 | supporting additional features such as BER encoding and decoding and ASN.1 23 | CHOICE types. 24 | 25 | By default and for convenience the package uses DER for encoding and BER for 26 | decoding. However it's possible to use a Context object to set the desired 27 | encoding and decoding rules as well other options. 28 | 29 | Restrictions: 30 | 31 | - BER allows STRING types, such as OCTET STRING and BIT STRING, to be encoded as 32 | constructed types containing inner elements that should be concatenated to form 33 | the complete string. The package does not support that, but in the future 34 | decoding of constructed strings should be included. 35 | 36 | ## Usage 37 | 38 | #### func Decode 39 | 40 | ```go 41 | func Decode(data []byte, obj interface{}) (rest []byte, err error) 42 | ``` 43 | Decode parses the given BER data into obj. The argument obj should be a 44 | reference to the value that will hold the parsed data. Decode uses a default 45 | Context and is equivalent to: 46 | 47 | rest, err := asn1.NewContext().Decode(data, &obj) 48 | 49 | #### func DecodeWithOptions 50 | 51 | ```go 52 | func DecodeWithOptions(data []byte, obj interface{}, options string) (rest []byte, err error) 53 | ``` 54 | DecodeWithOptions parses the given BER data into obj using the additional 55 | options. The argument obj should be a reference to the value that will hold the 56 | parsed data. Decode uses a default Context and is equivalent to: 57 | 58 | rest, err := asn1.NewContext().DecodeWithOptions(data, &obj, options) 59 | 60 | #### func Encode 61 | 62 | ```go 63 | func Encode(obj interface{}) (data []byte, err error) 64 | ``` 65 | Encode returns the DER encoding of obj. Encode uses a default Context and it's 66 | equivalent to: 67 | 68 | data, err = asn1.NewContext().Encode(obj) 69 | 70 | #### func EncodeWithOptions 71 | 72 | ```go 73 | func EncodeWithOptions(obj interface{}, options string) (data []byte, err error) 74 | ``` 75 | EncodeWithOptions returns the DER encoding of obj using additional options. 76 | EncodeWithOptions uses a default Context and it's equivalent to: 77 | 78 | data, err = asn1.NewContext().EncodeWithOptions(obj, options) 79 | 80 | #### type Choice 81 | 82 | ```go 83 | type Choice struct { 84 | Type reflect.Type 85 | Options string 86 | } 87 | ``` 88 | 89 | Choice represents one option available for a CHOICE element. 90 | 91 | #### type Context 92 | 93 | ```go 94 | type Context struct { 95 | } 96 | ``` 97 | 98 | Context keeps options that affect the ASN.1 encoding and decoding 99 | 100 | Use the NewContext() function to create a new Context instance: 101 | 102 | ctx := ber.NewContext() 103 | // Set options, ex: 104 | ctx.SetDer(true, true) 105 | // And call decode or encode functions 106 | bytes, err := ctx.EncodeWithOptions(value, "explicit,application,tag:5") 107 | ... 108 | 109 | #### func NewContext 110 | 111 | ```go 112 | func NewContext() *Context 113 | ``` 114 | NewContext creates and initializes a new context. The returned Context does not 115 | contains any registered choice and it's set to DER encoding and BER decoding. 116 | 117 | #### func (*Context) AddChoice 118 | 119 | ```go 120 | func (ctx *Context) AddChoice(choice string, entries []Choice) error 121 | ``` 122 | AddChoice registers a list of types as options to a given choice. 123 | 124 | The string choice refers to a choice name defined into an element via additional 125 | options for DecodeWithOptions and EncodeWithOptions of via struct tags. 126 | 127 | For example, considering that a field "Value" can be an INTEGER or an OCTET 128 | STRING indicating two types of errors, each error with a different tag number, 129 | the following can be used: 130 | 131 | // Error types 132 | type SimpleError string 133 | type ComplextError string 134 | // The main object 135 | type SomeSequence struct { 136 | // ... 137 | Value interface{} `asn1:"choice:value"` 138 | // ... 139 | } 140 | // A Context with the registered choices 141 | ctx := asn1.NewContext() 142 | ctx.AddChoice("value", []asn1.Choice { 143 | { 144 | Type: reflect.TypeOf(int(0)), 145 | }, 146 | { 147 | Type: reflect.TypeOf(SimpleError("")), 148 | Options: "tag:1", 149 | }, 150 | { 151 | Type: reflect.TypeOf(ComplextError("")), 152 | Options: "tag:2", 153 | }, 154 | }) 155 | 156 | Some important notes: 157 | 158 | 1. Any choice value must be an interface. During decoding the necessary type 159 | will be allocated to keep the parsed value. 160 | 161 | 2. The INTEGER type will be encoded using its default class and tag number and 162 | so it's not necessary to specify any Options for it. 163 | 164 | 3. The two error types in our example are encoded as strings, in order to make 165 | possible to differentiate both types during encoding they actually need to be 166 | different types. This is solved by defining two alias types: SimpleError and 167 | ComplextError. 168 | 169 | 4. Since both errors use the same encoding type, ASN.1 says they must have 170 | distinguished tags. For that, the appropriate tag is defined for each type. 171 | 172 | To encode a choice value, all that is necessary is to set the choice field with 173 | the proper object. To decode a choice value, a type switch can be used to 174 | determine which type was used. 175 | 176 | #### func (*Context) Decode 177 | 178 | ```go 179 | func (ctx *Context) Decode(data []byte, obj interface{}) (rest []byte, err error) 180 | ``` 181 | Decode parses the given data into obj. The argument obj should be a reference to 182 | the value that will hold the parsed data. 183 | 184 | See (*Context).DecodeWithOptions() for further details. 185 | 186 | #### func (*Context) DecodeWithOptions 187 | 188 | ```go 189 | func (ctx *Context) DecodeWithOptions(data []byte, obj interface{}, options string) (rest []byte, err error) 190 | ``` 191 | DecodeWithOptions parses the given data into obj using the additional options. 192 | The argument obj should be a reference to the value that will hold the parsed 193 | data. 194 | 195 | It uses the reflect package to inspect obj and because of that only exported 196 | struct fields (those that start with a capital letter) are considered. 197 | 198 | The Context object defines the decoding rules (BER or DER) and the types 199 | available for CHOICE types. 200 | 201 | The asn1 package maps Go types to ASN.1 data structures. The package also 202 | provides types to specific ASN.1 data structures. The default mapping is shown 203 | in the table below: 204 | 205 | Go type | ASN.1 universal tag 206 | -----------------------|-------------------- 207 | bool | BOOLEAN 208 | All int and uint types | INTEGER 209 | *big.Int | INTEGER 210 | string | OCTET STRING 211 | []byte | OCTET STRING 212 | asn1.Oid | OBJECT INDETIFIER 213 | asn1.Null | NULL 214 | Any array or slice | SEQUENCE OF 215 | Any struct | SEQUENCE 216 | 217 | Arrays and slices are decoded using different rules. A slice is always appended 218 | while an array requires an exact number of elements, otherwise a ParseError is 219 | returned. 220 | 221 | The default mapping can be changed using options provided in the argument 222 | options (for the root value) or via struct tags for struct fields. Struct tags 223 | use the namei space "asn1". 224 | 225 | The available options for encoding and decoding are: 226 | 227 | tag 228 | 229 | This option requires an numeric argument (ie: "tag:1") and indicates that a 230 | element is encoded and decoded as a context specific element with the given tag 231 | number. The context specific class can be overridden with the options 232 | "application" or "universal". 233 | 234 | universal 235 | 236 | Sets the tag class to universal. Requires "tag". 237 | 238 | application 239 | 240 | Sets the tag class to application. Requires "tag". 241 | 242 | explicit 243 | 244 | Indicates the element is encoded with an enclosing tag. It's usually used in 245 | conjunction with "tag". 246 | 247 | optional 248 | 249 | Indicates that an element can be suppressed. 250 | 251 | A missing element that is not marked with "optional" or "default" causes a 252 | ParseError to be returned during decoding. A missing element marked as optional 253 | is left untouched. 254 | 255 | During encoding, a zero value elements is suppressed from output if it's marked 256 | as optional. 257 | 258 | default 259 | 260 | This option is handled similarly to the "optional" option but requires a numeric 261 | argument (ie: "default:1"). 262 | 263 | A missing element that is marked with "default" is set to the given default 264 | value during decoding. 265 | 266 | A zero value marked with "default" is suppressed from output when encoding is 267 | set to DER or is encoded with the given default value when encoding is set to 268 | BER. 269 | 270 | indefinite 271 | 272 | This option is used only during encoding and causes a constructed element to be 273 | encoded using the indefinite form. 274 | 275 | choice 276 | 277 | Indicates that an element can be of one of several types as defined by 278 | (*Context).AddChoice() 279 | 280 | set 281 | 282 | Indicates that a struct, array or slice should be encoded and decoded as a SET 283 | instead of a SEQUENCE. 284 | 285 | It also affects the way that structs are encoded and decoded in DER. A struct 286 | marked with "set" has its fields always encoded in the ascending order of its 287 | tags, instead of following the order that the fields are defined in the struct. 288 | 289 | Similarly, a struct marked with "set" always enforces that same order when 290 | decoding in DER. 291 | 292 | #### func (*Context) Encode 293 | 294 | ```go 295 | func (ctx *Context) Encode(obj interface{}) (data []byte, err error) 296 | ``` 297 | Encode returns the ASN.1 encoding of obj. 298 | 299 | See (*Context).EncodeWithOptions() for further details. 300 | 301 | #### func (*Context) EncodeWithOptions 302 | 303 | ```go 304 | func (ctx *Context) EncodeWithOptions(obj interface{}, options string) (data []byte, err error) 305 | ``` 306 | EncodeWithOptions returns the ASN.1 encoding of obj using additional options. 307 | 308 | See (*Context).DecodeWithOptions() for further details regarding types and 309 | options. 310 | 311 | #### func (*Context) SetDer 312 | 313 | ```go 314 | func (ctx *Context) SetDer(encoding bool, decoding bool) 315 | ``` 316 | SetDer sets DER mode for encofing and decoding. 317 | 318 | #### func (*Context) SetLogger 319 | 320 | ```go 321 | func (ctx *Context) SetLogger(logger *log.Logger) 322 | ``` 323 | SetLogger defines the logger used. 324 | 325 | #### type Null 326 | 327 | ```go 328 | type Null struct{} 329 | ``` 330 | 331 | Null is used to encode and decode ASN.1 NULLs. 332 | 333 | #### type Oid 334 | 335 | ```go 336 | type Oid []uint 337 | ``` 338 | 339 | Oid is used to encode and decode ASN.1 OBJECT IDENTIFIERs. 340 | 341 | #### func (Oid) Cmp 342 | 343 | ```go 344 | func (oid Oid) Cmp(other Oid) int 345 | ``` 346 | Cmp returns zero if both Oids are the same, a negative value if oid 347 | lexicographically precedes other and a positive value otherwise. 348 | 349 | #### func (Oid) String 350 | 351 | ```go 352 | func (oid Oid) String() string 353 | ``` 354 | String returns the dotted representation of oid. 355 | 356 | #### type ParseError 357 | 358 | ```go 359 | type ParseError struct { 360 | Msg string 361 | } 362 | ``` 363 | 364 | ParseError is returned by the package to indicate that the given data is 365 | invalid. 366 | 367 | #### func (*ParseError) Error 368 | 369 | ```go 370 | func (e *ParseError) Error() string 371 | ``` 372 | Error returns the error message of a ParseError. 373 | 374 | #### type SyntaxError 375 | 376 | ```go 377 | type SyntaxError struct { 378 | Msg string 379 | } 380 | ``` 381 | 382 | SyntaxError is returned by the package to indicate that the given value or 383 | struct is invalid. 384 | 385 | #### func (*SyntaxError) Error 386 | 387 | ```go 388 | func (e *SyntaxError) Error() string 389 | ``` 390 | Error returns the error message of a SyntaxError. 391 | -------------------------------------------------------------------------------- /asn1.go: -------------------------------------------------------------------------------- 1 | // Package asn1 implements encoding and decoding of ASN.1 data structures using 2 | // both Basic Encoding Rules (BER) or its subset, the Distinguished Encoding 3 | // Rules (BER). 4 | // 5 | // This package is highly inspired by the Go standard package "encoding/asn1" 6 | // while supporting additional features such as BER encoding and decoding and 7 | // ASN.1 CHOICE types. 8 | // 9 | // By default and for convenience the package uses DER for encoding and BER for 10 | // decoding. However it's possible to use a Context object to set the desired 11 | // encoding and decoding rules as well other options. 12 | // 13 | // Restrictions: 14 | // 15 | // - BER allows STRING types, such as OCTET STRING and BIT STRING, to be 16 | // encoded as constructed types containing inner elements that should be 17 | // concatenated to form the complete string. The package does not support that, 18 | // but in the future decoding of constructed strings should be included. 19 | package asn1 20 | 21 | // TODO add a mechanism for extendability 22 | // TODO proper checking of the constructed flag 23 | // TODO support for constructed encoding and decoding of string types in BER 24 | 25 | import ( 26 | "fmt" 27 | "reflect" 28 | ) 29 | 30 | // Internal constants. 31 | const ( 32 | tagKey = "asn1" 33 | ) 34 | 35 | // Encode returns the DER encoding of obj. Encode uses a default Context and 36 | // it's equivalent to: 37 | // 38 | // data, err = asn1.NewContext().Encode(obj) 39 | // 40 | func Encode(obj interface{}) (data []byte, err error) { 41 | ctx := NewContext() 42 | return ctx.EncodeWithOptions(obj, "") 43 | } 44 | 45 | // EncodeWithOptions returns the DER encoding of obj using additional options. 46 | // EncodeWithOptions uses a default Context and it's equivalent to: 47 | // 48 | // data, err = asn1.NewContext().EncodeWithOptions(obj, options) 49 | // 50 | func EncodeWithOptions(obj interface{}, options string) (data []byte, err error) { 51 | ctx := NewContext() 52 | return ctx.EncodeWithOptions(obj, options) 53 | } 54 | 55 | // Decode parses the given BER data into obj. The argument obj should be a 56 | // reference to the value that will hold the parsed data. Decode uses a 57 | // default Context and is equivalent to: 58 | // 59 | // rest, err := asn1.NewContext().Decode(data, &obj) 60 | // 61 | func Decode(data []byte, obj interface{}) (rest []byte, err error) { 62 | ctx := NewContext() 63 | return ctx.DecodeWithOptions(data, obj, "") 64 | } 65 | 66 | // DecodeWithOptions parses the given BER data into obj using the additional 67 | // options. The argument obj should be a reference to the value that will hold 68 | // the parsed data. Decode uses a default Context and is equivalent to: 69 | // 70 | // rest, err := asn1.NewContext().DecodeWithOptions(data, &obj, options) 71 | // 72 | func DecodeWithOptions(data []byte, obj interface{}, options string) (rest []byte, err error) { 73 | ctx := NewContext() 74 | return ctx.DecodeWithOptions(data, obj, options) 75 | } 76 | 77 | // ParseError is returned by the package to indicate that the given data is 78 | // invalid. 79 | type ParseError struct { 80 | Msg string 81 | } 82 | 83 | // Error returns the error message of a ParseError. 84 | func (e *ParseError) Error() string { 85 | return e.Msg 86 | } 87 | 88 | // parseError allocates a new ParseError. 89 | func parseError(msg string, args ...interface{}) *ParseError { 90 | return &ParseError{fmt.Sprintf(msg, args...)} 91 | } 92 | 93 | // SyntaxError is returned by the package to indicate that the given value or 94 | // struct is invalid. 95 | type SyntaxError struct { 96 | Msg string 97 | } 98 | 99 | // Error returns the error message of a SyntaxError. 100 | func (e *SyntaxError) Error() string { 101 | return e.Msg 102 | } 103 | 104 | // syntaxError allocates a new ParseError, 105 | func syntaxError(msg string, args ...interface{}) *SyntaxError { 106 | return &SyntaxError{fmt.Sprintf(msg, args...)} 107 | } 108 | 109 | // setDefaultValue sets a reflected value to its default value based on the 110 | // field options. 111 | func (ctx *Context) setDefaultValue(value reflect.Value, opts *fieldOptions) error { 112 | switch value.Kind() { 113 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 114 | value.SetInt(int64(*opts.defaultValue)) 115 | 116 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 117 | value.SetUint(uint64(*opts.defaultValue)) 118 | 119 | default: 120 | return syntaxError("default value is only allowed to integers") 121 | } 122 | return nil 123 | } 124 | 125 | // newDefaultValue creates a new reflected value and sets it to its default value. 126 | func (ctx *Context) newDefaultValue(objType reflect.Type, opts *fieldOptions) (reflect.Value, error) { 127 | value := reflect.New(objType).Elem() 128 | if opts.defaultValue == nil { 129 | return value, nil 130 | } 131 | return value, ctx.setDefaultValue(value, opts) 132 | } 133 | -------------------------------------------------------------------------------- /asn1_test.go: -------------------------------------------------------------------------------- 1 | package asn1 2 | 3 | import ( 4 | "math/big" 5 | "reflect" 6 | "testing" 7 | ) 8 | 9 | // isBytesEqual compares two byte arrays/slices. 10 | func isBytesEqual(a, b []byte) bool { 11 | if len(a) != len(b) { 12 | return false 13 | } 14 | for i := range a { 15 | if a[i] != b[i] { 16 | return false 17 | } 18 | } 19 | return true 20 | } 21 | 22 | // testCase represents a decoding/encoding test case with a target object and 23 | // a expected sequence of bytes. 24 | type testCase struct { 25 | value interface{} 26 | expected []byte 27 | } 28 | 29 | // testEncode encodes an object and compares with the expected bytes. 30 | func testEncode(t *testing.T, ctx *Context, options string, tests ...testCase) { 31 | for _, test := range tests { 32 | data, err := ctx.EncodeWithOptions(test.value, options) 33 | if err != nil { 34 | t.Fatal(err) 35 | } 36 | if !isBytesEqual(data, test.expected) { 37 | t.Fatalf("Failed to encode \"%v\".\n Expected: %#v.\n Got: %#v", 38 | test.value, test.expected, data) 39 | } 40 | } 41 | } 42 | 43 | func checkEqual(t *testing.T, obj1 interface{}, obj2 interface{}) { 44 | equal := false 45 | switch val1 := obj1.(type) { 46 | case *big.Int: 47 | val2, ok := obj2.(*big.Int) 48 | equal = ok && val1.Cmp(val2) == 0 49 | default: 50 | equal = reflect.DeepEqual(obj1, obj2) 51 | } 52 | if !equal { 53 | t.Fatalf("Decoded value does not match.\n Got \"%v\" (%T)\n When decoding \"%v\" (%T)", 54 | obj1, obj1, obj2, obj2) 55 | } 56 | } 57 | 58 | // testEncode decodes a sequence of bytes and compares with the target object. 59 | func testDecode(t *testing.T, ctx *Context, options string, tests ...testCase) { 60 | for _, test := range tests { 61 | value := reflect.New(reflect.TypeOf(test.value)) 62 | rest, err := ctx.DecodeWithOptions(test.expected, value.Interface(), options) 63 | if err != nil { 64 | t.Fatal(err) 65 | } 66 | if len(rest) > 0 { 67 | t.Fatalf("Unexpected remaining bytes when decoding \"%v\": %#v\n", 68 | test.value, rest) 69 | } 70 | checkEqual(t, value.Elem().Interface(), test.value) 71 | } 72 | } 73 | 74 | // testEncodeDecode does testEncode and testDecode. 75 | func testEncodeDecode(t *testing.T, ctx *Context, options string, tests ...testCase) { 76 | for _, test := range tests { 77 | testEncode(t, ctx, options, test) 78 | testDecode(t, ctx, options, test) 79 | } 80 | } 81 | 82 | // testSimple encodes an object, decodes the resulting bytes and then compared the 83 | // two objects. 84 | func testSimple(t *testing.T, ctx *Context, options string, objs ...interface{}) { 85 | for _, obj := range objs { 86 | data, err := ctx.EncodeWithOptions(obj, options) 87 | if err != nil { 88 | t.Fatal(err) 89 | } 90 | value := reflect.New(reflect.TypeOf(obj)) 91 | rest, err := ctx.DecodeWithOptions(data, value.Interface(), options) 92 | if err != nil { 93 | t.Fatal(err) 94 | } 95 | if len(rest) > 0 { 96 | t.Fatalf("Unexpected remaining bytes when decoding \"%v\": %#v\n", 97 | obj, rest) 98 | } 99 | checkEqual(t, obj, value.Elem().Interface()) 100 | } 101 | } 102 | 103 | func TestContext(t *testing.T) { 104 | target := 0 105 | // Without options 106 | data, err := Encode(0) 107 | if err != nil { 108 | t.Fatal(err) 109 | } 110 | _, err = Decode(data, &target) 111 | if err != nil { 112 | t.Fatal(err) 113 | } 114 | // With options 115 | data, err = EncodeWithOptions(0, "tag:1") 116 | if err != nil { 117 | t.Fatal(err) 118 | } 119 | _, err = DecodeWithOptions(data, &target, "tag:1") 120 | if err != nil { 121 | t.Fatal(err) 122 | } 123 | } 124 | 125 | func TestSimpleBool(t *testing.T) { 126 | ctx := NewContext() 127 | // Simple test 128 | testEncodeDecode(t, ctx, "", testCase{false, []byte{0x01, 0x01, 0x00}}) 129 | testEncodeDecode(t, ctx, "", testCase{true, []byte{0x01, 0x01, 0xff}}) 130 | testDecode(t, ctx, "", testCase{true, []byte{0x01, 0x01, 0x01}}) 131 | // Der test 132 | ctx.SetDer(true, true) 133 | testEncodeDecode(t, ctx, "", testCase{false, []byte{0x01, 0x01, 0x00}}) 134 | testEncodeDecode(t, ctx, "", testCase{true, []byte{0x01, 0x01, 0xff}}) 135 | // Test Der invalid boolean 136 | boolean := false 137 | _, err := ctx.Decode([]byte{0x01, 0x01, 0x01}, &boolean) 138 | if err == nil { 139 | t.Fatal("DER boolean should accept only the simplest form.") 140 | } else { 141 | if _, ok := err.(*ParseError); !ok { 142 | t.Fatal(err) 143 | } 144 | } 145 | } 146 | 147 | func TestSimpleInteger(t *testing.T) { 148 | tests := []testCase{ 149 | // int 150 | {0, []byte{0x02, 0x01, 0x00}}, 151 | {1, []byte{0x02, 0x01, 0x01}}, 152 | {255, []byte{0x02, 0x02, 0x00, 0xff}}, 153 | {-1, []byte{0x02, 0x01, 0xff}}, 154 | {1000, []byte{0x02, 0x02, 0x03, 0xe8}}, 155 | {-1000, []byte{0x02, 0x02, 0xfc, 0x18}}, 156 | // uint 157 | {uint(0), []byte{0x02, 0x01, 0x00}}, 158 | {uint(1), []byte{0x02, 0x01, 0x01}}, 159 | {uint(127), []byte{0x02, 0x01, 0x7f}}, 160 | {uint(256 - 1), []byte{0x02, 0x02, 0x00, 0xff}}, 161 | {uint(256*256 - 1), []byte{0x02, 0x03, 0x00, 0xff, 0xff}}, 162 | // big.Int 163 | {big.NewInt(0), []byte{0x02, 0x01, 0x00}}, 164 | {big.NewInt(1), []byte{0x02, 0x01, 0x01}}, 165 | {big.NewInt(-1), []byte{0x02, 0x01, 0xff}}, 166 | { 167 | big.NewInt(0).SetBit(big.NewInt(0), 128, 1), 168 | []byte{ 169 | 0x02, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 170 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 171 | 0x00, 0x00, 0x00, 172 | }, 173 | }, 174 | { 175 | big.NewInt(0).Neg(big.NewInt(0).SetBit(big.NewInt(0), 128, 1)), 176 | []byte{ 177 | 0x02, 0x11, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 178 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 179 | 0x00, 0x00, 0x00, 180 | }, 181 | }, 182 | } 183 | ctx := NewContext() 184 | testEncodeDecode(t, ctx, "", tests...) 185 | } 186 | 187 | func TestSimpleString(t *testing.T) { 188 | lenStr := func(length int, lenBytes ...byte) testCase { 189 | buf := make([]byte, length) 190 | return testCase{ 191 | string(buf), 192 | append(append([]byte{0x04}, lenBytes...), buf...), 193 | } 194 | } 195 | tests := []testCase{ 196 | // int 197 | {"", []byte{0x04, 0x00}}, 198 | {"a", []byte{0x04, 0x01, 0x61}}, 199 | {"abc", []byte{0x04, 0x03, 0x61, 0x62, 0x63}}, 200 | lenStr(127, 0x7f), 201 | lenStr(255, 0x81, 0xff), 202 | } 203 | ctx := NewContext() 204 | testEncodeDecode(t, ctx, "", tests...) 205 | } 206 | 207 | func TestUtf8String(t *testing.T) { 208 | ctx := NewContext() 209 | testEncodeDecode(t, ctx, "universal,tag:12", testCase{ 210 | "test", 211 | []byte{0x0c, 0x04, 0x74, 0x65, 0x73, 0x74}, 212 | }) 213 | } 214 | 215 | func TestOctetString(t *testing.T) { 216 | tests := []testCase{ 217 | { 218 | []byte{}, 219 | []byte{0x04, 0x00}, 220 | }, 221 | { 222 | []byte{0x00}, 223 | []byte{0x04, 0x01, 0x00}, 224 | }, 225 | { 226 | []byte{0x01, 0x02, 0x03}, 227 | []byte{0x04, 0x03, 0x01, 0x02, 0x03}, 228 | }, 229 | { 230 | [...]byte{}, 231 | []byte{0x04, 0x00}, 232 | }, 233 | { 234 | [...]byte{0x00}, 235 | []byte{0x04, 0x01, 0x00}, 236 | }, 237 | { 238 | [...]byte{0x01, 0x02, 0x03}, 239 | []byte{0x04, 0x03, 0x01, 0x02, 0x03}, 240 | }, 241 | } 242 | ctx := NewContext() 243 | testEncodeDecode(t, ctx, "", tests...) 244 | // Tests that should fail 245 | tests = []testCase{ 246 | { 247 | [0]byte{}, 248 | []byte{0x04, 0x01, 0x00}, 249 | }, 250 | { 251 | [2]byte{}, 252 | []byte{0x04, 0x01, 0x00}, 253 | }, 254 | } 255 | for _, test := range tests { 256 | _, err := ctx.Decode(test.expected, test) 257 | if err == nil { 258 | t.Fatal("OctetString with length different from array should have failed.") 259 | } 260 | } 261 | } 262 | 263 | func TestSimpleOid(t *testing.T) { 264 | // Cases that encoding and decoding do not match 265 | tests := []testCase{ 266 | {Oid{}, []byte{0x06, 0x01, 0x00}}, 267 | {Oid{0}, []byte{0x06, 0x01, 0x00}}, 268 | {Oid{1}, []byte{0x06, 0x01, 0x28}}, 269 | {Oid{2}, []byte{0x06, 0x01, 0x50}}, 270 | } 271 | ctx := NewContext() 272 | testEncode(t, ctx, "", tests...) 273 | 274 | // Cases that de/encoding match: 275 | tests = []testCase{ 276 | {Oid{0, 0}, []byte{0x06, 0x01, 0x00}}, 277 | {Oid{0, 39}, []byte{0x06, 0x01, 0x27}}, 278 | {Oid{1, 0}, []byte{0x06, 0x01, 0x28}}, 279 | {Oid{1, 39}, []byte{0x06, 0x01, 0x4f}}, 280 | {Oid{2, 0}, []byte{0x06, 0x01, 0x50}}, 281 | {Oid{2, 39}, []byte{0x06, 0x01, 0x77}}, 282 | {Oid{0, 0, 0}, []byte{0x06, 0x02, 0x00, 0x00}}, 283 | {Oid{0, 0, 1}, []byte{0x06, 0x02, 0x00, 0x01}}, 284 | {Oid{0, 0, 127}, []byte{0x06, 0x02, 0x00, 0x07f}}, 285 | {Oid{0, 0, 128}, []byte{0x06, 0x03, 0x00, 0x81, 0x00}}, 286 | {Oid{0, 0, 255}, []byte{0x06, 0x03, 0x00, 0x81, 0x7f}}, 287 | {Oid{0, 0, 1000}, []byte{0x06, 0x03, 0x00, 0x87, 0x68}}, 288 | {Oid{0, 0, ^uint(0)}, []byte{0x06, 0x0b, 0x00, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}}, 289 | } 290 | testEncodeDecode(t, ctx, "", tests...) 291 | 292 | // Cases that should fail 293 | oids := []Oid{ 294 | {3, 0}, {4, 0}, {5, 0}, {256, 0}, 295 | {0, 40}, {0, 41}, {0, 256}, 296 | } 297 | for _, oid := range oids { 298 | _, err := ctx.Encode(oid) 299 | if err == nil { 300 | t.Fatalf("OID %v is invalid and encoding should have failed.", oid) 301 | } 302 | } 303 | } 304 | 305 | func TestCmpOid(t *testing.T) { 306 | tests := []struct { 307 | s int 308 | a, b Oid 309 | }{ 310 | {1, Oid{1, 1, 10, 10}, Oid{0}}, 311 | {1, Oid{1, 1, 10, 10}, Oid{0, 1}}, 312 | {1, Oid{1, 1, 10, 10}, Oid{0, 0, 0, 0, 0, 0, 0}}, 313 | {1, Oid{1, 1, 10, 10}, Oid{0, 10}}, 314 | {1, Oid{1, 1, 10, 10}, Oid{1, 0}}, 315 | {1, Oid{1, 1, 10, 10}, Oid{1, 1}}, 316 | {1, Oid{1, 1, 10, 10}, Oid{1, 1, 1}}, 317 | {1, Oid{1, 1, 10, 10}, Oid{1, 1, 10}}, 318 | {1, Oid{1, 1, 10, 10}, Oid{1, 1, 10, 1}}, 319 | {1, Oid{1, 1, 10, 10}, Oid{1, 1, 10, 9}}, 320 | {0, Oid{1, 1, 10, 10}, Oid{1, 1, 10, 10}}, 321 | {-1, Oid{1, 1, 10, 10}, Oid{1, 1, 10, 11}}, 322 | {-1, Oid{1, 1, 10, 10}, Oid{1, 1, 10, 10, 0}}, 323 | {-1, Oid{1, 1, 10, 10}, Oid{1, 1, 11}}, 324 | {-1, Oid{1, 1, 10, 10}, Oid{1, 1, 11, 0}}, 325 | {-1, Oid{1, 1, 10, 10}, Oid{2}}, 326 | } 327 | op := map[int]string{1: ">", 0: "=", -1: "<"} 328 | for _, test := range tests { 329 | cmp := test.a.Cmp(test.b) 330 | if cmp > 0 { 331 | cmp = 1 332 | } else if cmp < 0 { 333 | cmp = -1 334 | } 335 | if cmp != test.s { 336 | t.Fatalf("Wrong comparison.\n\tExpected %s %s %s\n\tGot: %s %s %s", 337 | test.a, op[test.s], test.b, test.a, op[cmp], test.b) 338 | } 339 | } 340 | } 341 | 342 | func TestSimpleNull(t *testing.T) { 343 | tests := []testCase{ 344 | {Null{}, []byte{0x05, 0x00}}, 345 | } 346 | ctx := NewContext() 347 | testEncodeDecode(t, ctx, "", tests...) 348 | } 349 | 350 | func TestSequence(t *testing.T) { 351 | type Type struct { 352 | A int 353 | B string 354 | C bool 355 | } 356 | obj := Type{1, "abc", true} 357 | ctx := NewContext() 358 | testSimple(t, ctx, "", obj) 359 | } 360 | 361 | func TestSet(t *testing.T) { 362 | type Type struct { 363 | A int 364 | B string 365 | C bool 366 | } 367 | obj := Type{1, "abc", true} 368 | ctx := NewContext() 369 | testSimple(t, ctx, "set", obj) 370 | } 371 | 372 | func TestBerSet(t *testing.T) { 373 | type Type struct { 374 | A int 375 | B string 376 | C bool 377 | } 378 | elem := Type{1, "abc", true} 379 | ctx := NewContext() 380 | data, err := ctx.EncodeWithOptions(elem, "set") 381 | if err != nil { 382 | t.Fatal(err) 383 | } 384 | type RevType struct { 385 | C bool 386 | B string 387 | A int 388 | } 389 | revElem := RevType{} 390 | _, err = ctx.DecodeWithOptions(data, &revElem, "set") 391 | if err != nil { 392 | t.Fatal(err) 393 | } 394 | if elem.A != revElem.A || 395 | elem.B != revElem.B || 396 | elem.C != revElem.C { 397 | t.Fatalf("Sets does not match:\n %#v\n %#v", elem, revElem) 398 | } 399 | } 400 | 401 | func TestDerSet(t *testing.T) { 402 | // Thos test uses BER for encoding and DER for decoding. When the library 403 | // encodes SETs in BER mode it keeps the order of the fields since it allows 404 | // SET elements to appear in any order. However DER forces SETs elements to be 405 | // encoded in ascending order of their tag numbers. 406 | ctx := NewContext() 407 | ctx.SetDer(false, true) 408 | 409 | type Type struct { 410 | A int // tag = 2 411 | B string // tag = 3 412 | C bool // tag = 1 413 | } 414 | 415 | // Encode with BER. 416 | elem := Type{A: 1, B: "abc", C: true} 417 | data, err := ctx.EncodeWithOptions(elem, "set") 418 | if err != nil { 419 | t.Fatal(err) 420 | } 421 | 422 | // Encode with DER. Should return an error. 423 | elem = Type{} 424 | _, err = ctx.DecodeWithOptions(data, &elem, "set") 425 | if err == nil { 426 | t.Fatal("Der decoding of a SET with non sorted element should have failed.") 427 | } 428 | if _, ok := err.(*ParseError); !ok { 429 | t.Fatal("Unexpected error:", err) 430 | } 431 | } 432 | 433 | func TestOptional(t *testing.T) { 434 | type Type struct { 435 | A int `asn1:"optional"` 436 | B string 437 | C bool 438 | } 439 | test := testCase{ 440 | Type{0, "abc", true}, 441 | []byte{ 442 | // SEQ LEN=8 443 | 0x30, 0x08, 444 | // OCTETSTRING LEN=3 445 | 0x04, 0x03, 446 | // "abc" 447 | 0x61, 0x62, 0x63, 448 | // BOOLEAN LEN=1 449 | 0x01, 0x01, 450 | // true 451 | 0xff, 452 | }, 453 | } 454 | ctx := NewContext() 455 | testEncodeDecode(t, ctx, "", test) 456 | } 457 | 458 | func TestEncodeDefaultBer(t *testing.T) { 459 | type Type struct { 460 | A1 int `asn1:"default:-1"` 461 | A2 uint `asn1:"default:127"` 462 | B string 463 | C bool 464 | } 465 | test := testCase{ 466 | Type{0, 0, "abc", true}, 467 | []byte{ 468 | // SEQ LEN=14 469 | 0x30, 0x0e, 470 | // INTEGER LEN=1 471 | 0x02, 0x01, 472 | // -1 473 | 0xff, 474 | // INTEGER LEN=1 475 | 0x02, 0x01, 476 | // 127 477 | 0x7f, 478 | // OCTETSTRING LEN=3 479 | 0x04, 0x03, 480 | // "abc" 481 | 0x61, 0x62, 0x63, 482 | // BOOLEAN LEN=1 483 | 0x01, 0x01, 484 | // true 485 | 0xff, 486 | }, 487 | } 488 | ctx := NewContext() 489 | ctx.SetDer(false, false) 490 | testEncode(t, ctx, "", test) 491 | } 492 | 493 | func TestEncodeDefaultDer(t *testing.T) { 494 | type Type struct { 495 | A int `asn1:"default:127"` 496 | B string 497 | C bool 498 | } 499 | test := testCase{ 500 | Type{0, "abc", true}, 501 | []byte{ 502 | // SEQ LEN=8 503 | 0x30, 0x08, 504 | // OCTETSTRING LEN=3 505 | 0x04, 0x03, 506 | // "abc" 507 | 0x61, 0x62, 0x63, 508 | // BOOLEAN LEN=1 509 | 0x01, 0x01, 510 | // true 511 | 0xff, 512 | }, 513 | } 514 | ctx := NewContext() 515 | ctx.SetDer(true, true) 516 | testEncode(t, ctx, "", test) 517 | } 518 | 519 | func TestTag(t *testing.T) { 520 | ctx := NewContext() 521 | testEncodeDecode(t, ctx, "tag:1", testCase{ 522 | false, 523 | []byte{0x81, 0x01, 0x00}, 524 | }) 525 | testEncodeDecode(t, ctx, "explicit,tag:1", testCase{ 526 | true, 527 | []byte{0xa1, 0x03, 0x01, 0x01, 0xff}, 528 | }) 529 | testEncodeDecode(t, ctx, "explicit,application,tag:1", testCase{ 530 | false, 531 | []byte{0x61, 0x03, 0x01, 0x01, 0x00}, 532 | }) 533 | testEncodeDecode(t, ctx, "explicit,tag:1000", testCase{ 534 | true, 535 | []byte{0xbf, 0x87, 0x68, 0x3, 0x1, 0x1, 0xff}, 536 | }) 537 | 538 | } 539 | 540 | func TestIndefinite(t *testing.T) { 541 | type Type struct { 542 | Flag bool 543 | Num int 544 | } 545 | type NestedType struct { 546 | Nested Type `asn1:"indefinite"` 547 | } 548 | testCases := []testCase{ 549 | { 550 | Type{true, 0}, 551 | []byte{ 552 | 0x30, 0x80, 553 | 0x01, 0x01, 0xff, 554 | 0x02, 0x01, 0x00, 555 | 0x00, 0x00, 556 | }, 557 | }, 558 | { 559 | NestedType{Type{true, 0}}, 560 | []byte{ 561 | 0x30, 0x80, 562 | 0x30, 0x80, 563 | 0x01, 0x01, 0xff, 564 | 0x02, 0x01, 0x00, 565 | 0x00, 0x00, 566 | 0x00, 0x00, 567 | }, 568 | }, 569 | } 570 | ctx := NewContext() 571 | testEncodeDecode(t, ctx, "indefinite", testCases...) 572 | } 573 | 574 | func TestChoice(t *testing.T) { 575 | 576 | type Type struct { 577 | Num int 578 | Msg interface{} `asn1:"choice:msg"` 579 | } 580 | 581 | ctx := NewContext() 582 | ctx.AddChoice("msg", []Choice{ 583 | {reflect.TypeOf(""), "tag:0"}, 584 | {reflect.TypeOf(int(0)), "tag:1"}, 585 | }) 586 | 587 | choice := "abc" 588 | obj := Type{1, choice} 589 | data, err := ctx.Encode(obj) 590 | if err != nil { 591 | t.Fatal(err) 592 | } 593 | 594 | decodedObj := Type{} 595 | _, err = ctx.Decode(data, &decodedObj) 596 | if err != nil { 597 | t.Fatal(err) 598 | } 599 | 600 | if !reflect.DeepEqual(decodedObj.Msg, choice) { 601 | t.Fatalf("Incorrect choice value.\n Expected: %v\t Got: %v", choice, decodedObj.Msg) 602 | } 603 | } 604 | 605 | func TestExplicitChoice(t *testing.T) { 606 | ctx := NewContext() 607 | ctx.AddChoice("msg", []Choice{ 608 | {reflect.TypeOf(int(0)), "explicit,tag:0"}, 609 | {reflect.TypeOf(""), "explicit,tag:1"}, 610 | }) 611 | 612 | obj := "abc" 613 | data, err := ctx.EncodeWithOptions(obj, "choice:msg") 614 | if err != nil { 615 | t.Fatal(err) 616 | } 617 | 618 | var decodedObj interface{} 619 | _, err = ctx.DecodeWithOptions(data, &decodedObj, "choice:msg") 620 | if err != nil { 621 | t.Fatal("Error:", err) 622 | } 623 | 624 | if !reflect.DeepEqual(decodedObj, obj) { 625 | t.Fatalf("Incorrect choice value.\n Expected: %v\t Got: %v", obj, decodedObj) 626 | } 627 | } 628 | 629 | func TestNestedExplicitChoice(t *testing.T) { 630 | type Type struct { 631 | Num int 632 | Msg interface{} `asn1:"choice:msg"` 633 | } 634 | 635 | ctx := NewContext() 636 | ctx.AddChoice("msg", []Choice{ 637 | {reflect.TypeOf(int(0)), "explicit,tag:0"}, 638 | {reflect.TypeOf(""), "explicit,tag:1"}, 639 | }) 640 | 641 | choice := "abc" 642 | obj := Type{1, choice} 643 | data, err := ctx.Encode(obj) 644 | if err != nil { 645 | t.Fatal(err) 646 | } 647 | 648 | decodedObj := Type{} 649 | _, err = ctx.Decode(data, &decodedObj) 650 | if err != nil { 651 | t.Fatal(err) 652 | } 653 | 654 | if !reflect.DeepEqual(decodedObj.Msg, choice) { 655 | t.Fatalf("Incorrect choice value.\n Expected: %v\t Got: %v", choice, decodedObj.Msg) 656 | } 657 | } 658 | 659 | func TestArraySlice(t *testing.T) { 660 | testCases := []testCase{ 661 | { 662 | []int{0, 1, 2}, 663 | []byte{0x30, 0x09, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, 664 | }, 665 | { 666 | [...]int{0, 1, 2}, 667 | []byte{0x30, 0x09, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, 668 | }, 669 | } 670 | ctx := NewContext() 671 | testEncodeDecode(t, ctx, "", testCases...) 672 | } 673 | -------------------------------------------------------------------------------- /context.go: -------------------------------------------------------------------------------- 1 | package asn1 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "log" 7 | "reflect" 8 | ) 9 | 10 | // Context keeps options that affect the ASN.1 encoding and decoding 11 | // 12 | // Use the NewContext() function to create a new Context instance: 13 | // 14 | // ctx := ber.NewContext() 15 | // // Set options, ex: 16 | // ctx.SetDer(true, true) 17 | // // And call decode or encode functions 18 | // bytes, err := ctx.EncodeWithOptions(value, "explicit,application,tag:5") 19 | // ... 20 | // 21 | type Context struct { 22 | log *log.Logger 23 | choices map[string][]choiceEntry 24 | der struct { 25 | encoding bool 26 | decoding bool 27 | } 28 | } 29 | 30 | // Choice represents one option available for a CHOICE element. 31 | type Choice struct { 32 | Type reflect.Type 33 | Options string 34 | } 35 | 36 | // Internal register with information about the each CHOICE. 37 | type choiceEntry struct { 38 | expectedElement 39 | typ reflect.Type 40 | opts *fieldOptions 41 | } 42 | 43 | // NewContext creates and initializes a new context. The returned Context does 44 | // not contains any registered choice and it's set to DER encoding and BER 45 | // decoding. 46 | func NewContext() *Context { 47 | ctx := &Context{} 48 | ctx.log = defaultLogger() 49 | ctx.choices = make(map[string][]choiceEntry) 50 | ctx.SetDer(true, false) 51 | return ctx 52 | } 53 | 54 | // getChoices returns a list of choices for a given name. 55 | func (ctx *Context) getChoices(choice string) ([]choiceEntry, error) { 56 | entries := ctx.choices[choice] 57 | if entries == nil { 58 | return nil, syntaxError("invalid choice '%s'", choice) 59 | } 60 | return entries, nil 61 | } 62 | 63 | // getChoiceByType returns the choice associated to a given name and type. 64 | func (ctx *Context) getChoiceByType(choice string, t reflect.Type) (entry choiceEntry, err error) { 65 | entries, err := ctx.getChoices(choice) 66 | if err != nil { 67 | return 68 | } 69 | 70 | for _, current := range entries { 71 | if current.typ == t { 72 | entry = current 73 | return 74 | } 75 | } 76 | err = syntaxError("invalid Go type '%s' for choice '%s'", t, choice) 77 | return 78 | } 79 | 80 | // getChoiceByTag returns the choice associated to a given tag. 81 | func (ctx *Context) getChoiceByTag(choice string, class, tag uint) (entry choiceEntry, err error) { 82 | entries, err := ctx.getChoices(choice) 83 | if err != nil { 84 | return 85 | } 86 | 87 | for _, current := range entries { 88 | if current.class == class && current.tag == tag { 89 | entry = current 90 | return 91 | } 92 | } 93 | // TODO convert tag to text 94 | err = syntaxError("invalid tag [%d,%d] for choice '%s'", class, tag, choice) 95 | return 96 | } 97 | 98 | // addChoiceEntry adds a single choice to the list associated to a given name. 99 | func (ctx *Context) addChoiceEntry(choice string, entry choiceEntry) error { 100 | for _, current := range ctx.choices[choice] { 101 | if current.class == entry.class && current.tag == entry.tag { 102 | return fmt.Errorf( 103 | "choice already registered: %s{%d, %d}", 104 | choice, entry.class, entry.tag) 105 | } 106 | } 107 | ctx.choices[choice] = append(ctx.choices[choice], entry) 108 | return nil 109 | } 110 | 111 | // AddChoice registers a list of types as options to a given choice. 112 | // 113 | // The string choice refers to a choice name defined into an element via 114 | // additional options for DecodeWithOptions and EncodeWithOptions of via 115 | // struct tags. 116 | // 117 | // For example, considering that a field "Value" can be an INTEGER or an OCTET 118 | // STRING indicating two types of errors, each error with a different tag 119 | // number, the following can be used: 120 | // 121 | // // Error types 122 | // type SimpleError string 123 | // type ComplextError string 124 | // // The main object 125 | // type SomeSequence struct { 126 | // // ... 127 | // Value interface{} `asn1:"choice:value"` 128 | // // ... 129 | // } 130 | // // A Context with the registered choices 131 | // ctx := asn1.NewContext() 132 | // ctx.AddChoice("value", []asn1.Choice { 133 | // { 134 | // Type: reflect.TypeOf(int(0)), 135 | // }, 136 | // { 137 | // Type: reflect.TypeOf(SimpleError("")), 138 | // Options: "tag:1", 139 | // }, 140 | // { 141 | // Type: reflect.TypeOf(ComplextError("")), 142 | // Options: "tag:2", 143 | // }, 144 | // }) 145 | // 146 | // Some important notes: 147 | // 148 | // 1. Any choice value must be an interface. During decoding the necessary type 149 | // will be allocated to keep the parsed value. 150 | // 151 | // 2. The INTEGER type will be encoded using its default class and tag number 152 | // and so it's not necessary to specify any Options for it. 153 | // 154 | // 3. The two error types in our example are encoded as strings, in order to 155 | // make possible to differentiate both types during encoding they actually need 156 | // to be different types. This is solved by defining two alias types: 157 | // SimpleError and ComplextError. 158 | // 159 | // 4. Since both errors use the same encoding type, ASN.1 says they must have 160 | // distinguished tags. For that, the appropriate tag is defined for each type. 161 | // 162 | // To encode a choice value, all that is necessary is to set the choice field 163 | // with the proper object. To decode a choice value, a type switch can be used 164 | // to determine which type was used. 165 | // 166 | func (ctx *Context) AddChoice(choice string, entries []Choice) error { 167 | for _, e := range entries { 168 | opts, err := parseOptions(e.Options) 169 | if err != nil { 170 | return err 171 | } 172 | if opts.choice != nil { 173 | // TODO Add support for nested choices. 174 | return syntaxError( 175 | "nested choices are not allowed: '%s' inside '%s'", 176 | *opts.choice, choice) 177 | } 178 | raw := rawValue{} 179 | elem, err := ctx.getExpectedElement(&raw, e.Type, opts) 180 | if err != nil { 181 | return err 182 | } 183 | err = ctx.addChoiceEntry(choice, choiceEntry{ 184 | expectedElement: elem, 185 | typ: e.Type, 186 | opts: opts, 187 | }) 188 | if err != nil { 189 | return err 190 | } 191 | } 192 | return nil 193 | } 194 | 195 | // defaultLogger returns the default Logger. It's used to initialize a new context 196 | // or when the logger is set to nil. 197 | func defaultLogger() *log.Logger { 198 | return log.New(ioutil.Discard, "", 0) 199 | } 200 | 201 | // SetLogger defines the logger used. 202 | func (ctx *Context) SetLogger(logger *log.Logger) { 203 | if logger == nil { 204 | logger = defaultLogger() 205 | } 206 | ctx.log = logger 207 | } 208 | 209 | // SetDer sets DER mode for encofing and decoding. 210 | func (ctx *Context) SetDer(encoding bool, decoding bool) { 211 | ctx.der.encoding = encoding 212 | ctx.der.decoding = decoding 213 | } 214 | -------------------------------------------------------------------------------- /decode.go: -------------------------------------------------------------------------------- 1 | package asn1 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "reflect" 7 | "sort" 8 | ) 9 | 10 | // Expected values 11 | type expectedElement struct { 12 | class uint 13 | tag uint 14 | decoder decoderFunction 15 | } 16 | 17 | // Expected values for fields 18 | type expectedFieldElement struct { 19 | expectedElement 20 | value reflect.Value 21 | opts *fieldOptions 22 | } 23 | 24 | // Decode parses the given data into obj. The argument obj should be a reference 25 | // to the value that will hold the parsed data. 26 | // 27 | // See (*Context).DecodeWithOptions() for further details. 28 | // 29 | func (ctx *Context) Decode(data []byte, obj interface{}) (rest []byte, err error) { 30 | return ctx.DecodeWithOptions(data, obj, "") 31 | } 32 | 33 | // DecodeWithOptions parses the given data into obj using the additional 34 | // options. The argument obj should be a reference to the value that will hold 35 | // the parsed data. 36 | // 37 | // It uses the reflect package to inspect obj and because of that only exported 38 | // struct fields (those that start with a capital letter) are considered. 39 | // 40 | // The Context object defines the decoding rules (BER or DER) and the types 41 | // available for CHOICE types. 42 | // 43 | // The asn1 package maps Go types to ASN.1 data structures. The package also 44 | // provides types to specific ASN.1 data structures. The default mapping is 45 | // shown in the table below: 46 | // 47 | // Go type | ASN.1 universal tag 48 | // -----------------------|-------------------- 49 | // bool | BOOLEAN 50 | // All int and uint types | INTEGER 51 | // *big.Int | INTEGER 52 | // string | OCTET STRING 53 | // []byte | OCTET STRING 54 | // asn1.Oid | OBJECT INDETIFIER 55 | // asn1.Null | NULL 56 | // Any array or slice | SEQUENCE OF 57 | // Any struct | SEQUENCE 58 | // 59 | // Arrays and slices are decoded using different rules. A slice is always 60 | // appended while an array requires an exact number of elements, otherwise a 61 | // ParseError is returned. 62 | // 63 | // The default mapping can be changed using options provided in the argument 64 | // options (for the root value) or via struct tags for struct fields. Struct 65 | // tags use the namei space "asn1". 66 | // 67 | // The available options for encoding and decoding are: 68 | // 69 | // tag 70 | // 71 | // This option requires an numeric argument (ie: "tag:1") and indicates that a 72 | // element is encoded and decoded as a context specific element with the given 73 | // tag number. The context specific class can be overridden with the options 74 | // "application" or "universal". 75 | // 76 | // universal 77 | // 78 | // Sets the tag class to universal. Requires "tag". 79 | // 80 | // application 81 | // 82 | // Sets the tag class to application. Requires "tag". 83 | // 84 | // explicit 85 | // 86 | // Indicates the element is encoded with an enclosing tag. It's usually 87 | // used in conjunction with "tag". 88 | // 89 | // optional 90 | // 91 | // Indicates that an element can be suppressed. 92 | // 93 | // A missing element that is not marked with "optional" or "default" causes a 94 | // ParseError to be returned during decoding. A missing element marked as 95 | // optional is left untouched. 96 | // 97 | // During encoding, a zero value elements is suppressed from output if it's 98 | // marked as optional. 99 | // 100 | // default 101 | // 102 | // This option is handled similarly to the "optional" option but requires a 103 | // numeric argument (ie: "default:1"). 104 | // 105 | // A missing element that is marked with "default" is set to the given default 106 | // value during decoding. 107 | // 108 | // A zero value marked with "default" is suppressed from output when encoding 109 | // is set to DER or is encoded with the given default value when encoding is set 110 | // to BER. 111 | // 112 | // indefinite 113 | // 114 | // This option is used only during encoding and causes a constructed element to 115 | // be encoded using the indefinite form. 116 | // 117 | // choice 118 | // 119 | // Indicates that an element can be of one of several types as defined by 120 | // (*Context).AddChoice() 121 | // 122 | // set 123 | // 124 | // Indicates that a struct, array or slice should be encoded and decoded as a 125 | // SET instead of a SEQUENCE. 126 | // 127 | // It also affects the way that structs are encoded and decoded in DER. A struct 128 | // marked with "set" has its fields always encoded in the ascending order of its 129 | // tags, instead of following the order that the fields are defined in the 130 | // struct. 131 | // 132 | // Similarly, a struct marked with "set" always enforces that same order when 133 | // decoding in DER. 134 | // 135 | func (ctx *Context) DecodeWithOptions(data []byte, obj interface{}, options string) (rest []byte, err error) { 136 | 137 | opts, err := parseOptions(options) 138 | if err != nil { 139 | return nil, err 140 | } 141 | 142 | value := reflect.ValueOf(obj) 143 | switch value.Kind() { 144 | case reflect.Ptr, reflect.Interface: 145 | value = value.Elem() 146 | } 147 | 148 | if !value.CanSet() { 149 | return nil, syntaxError("go type '%s' is read-only", value.Type()) 150 | } 151 | 152 | reader := bytes.NewBuffer(data) 153 | err = ctx.decode(reader, value, opts) 154 | if err != nil { 155 | return nil, err 156 | } 157 | 158 | return reader.Bytes(), nil 159 | } 160 | 161 | // Main decode function 162 | func (ctx *Context) decode(reader io.Reader, value reflect.Value, opts *fieldOptions) error { 163 | 164 | // Parse an Asn.1 element 165 | raw, err := decodeRawValue(reader) 166 | if err != nil { 167 | return err 168 | } 169 | if ctx.der.decoding && raw.Indefinite { 170 | return parseError("indefinite length form is not supported by DER mode") 171 | } 172 | 173 | elem, err := ctx.getExpectedElement(raw, value.Type(), opts) 174 | if err != nil { 175 | return err 176 | } 177 | 178 | // And tag must match 179 | if raw.Class != elem.class || raw.Tag != elem.tag { 180 | ctx.log.Printf("%#v\n", opts) 181 | return parseError("expected tag (%d,%d) but found (%d,%d)", 182 | elem.class, elem.tag, raw.Class, raw.Tag) 183 | } 184 | 185 | return elem.decoder(raw.Content, value) 186 | } 187 | 188 | // getExpectedElement returns the expected element for a given type. raw is only 189 | // used as hint when decoding choices. 190 | // TODO: consider replacing raw for class and tag number. 191 | func (ctx *Context) getExpectedElement(raw *rawValue, elemType reflect.Type, opts *fieldOptions) (elem expectedElement, err error) { 192 | 193 | // Get the expected universal tag and its decoder for the given Go type 194 | elem, err = ctx.getUniversalTag(elemType, opts) 195 | if err != nil { 196 | return 197 | } 198 | 199 | // Modify the expected tag and decoder function based on the given options 200 | if opts.tag != nil { 201 | elem.class = classContextSpecific 202 | elem.tag = uint(*opts.tag) 203 | } 204 | if opts.universal { 205 | elem.class = classUniversal 206 | } 207 | if opts.application { 208 | elem.class = classApplication 209 | } 210 | 211 | if opts.explicit { 212 | elem.decoder = func(data []byte, value reflect.Value) error { 213 | // Unset previous flags 214 | opts.explicit = false 215 | opts.tag = nil 216 | opts.application = false 217 | // Parse child 218 | reader := bytes.NewBuffer(data) 219 | return ctx.decode(reader, value, opts) 220 | } 221 | return 222 | } 223 | 224 | if opts.choice != nil { 225 | // Get the registered choices 226 | var entry choiceEntry 227 | entry, err = ctx.getChoiceByTag(*opts.choice, raw.Class, raw.Tag) 228 | if err != nil { 229 | return 230 | } 231 | 232 | // Get the decoder for the new value 233 | elem.class, elem.tag = raw.Class, raw.Tag 234 | elem.decoder = func(data []byte, value reflect.Value) error { 235 | // Allocate a new value and set to the current one 236 | nestedValue := reflect.New(entry.typ).Elem() 237 | err = entry.decoder(data, nestedValue) 238 | if err != nil { 239 | return err 240 | } 241 | value.Set(nestedValue) 242 | return nil 243 | } 244 | } 245 | 246 | // At this point a decoder function already be found 247 | if elem.decoder == nil { 248 | err = parseError("go type not supported '%s'", elemType) 249 | } 250 | return 251 | } 252 | 253 | // getUniversalTag maps an type to a Asn.1 universal type. 254 | func (ctx *Context) getUniversalTag(objType reflect.Type, opts *fieldOptions) (elem expectedElement, err error) { 255 | 256 | elem.class = classUniversal 257 | 258 | // Special types: 259 | switch objType { 260 | case bigIntType: 261 | elem.tag = tagInteger 262 | elem.decoder = ctx.decodeBigInt 263 | case oidType: 264 | elem.tag = tagOid 265 | elem.decoder = ctx.decodeOid 266 | case nullType: 267 | elem.tag = tagNull 268 | elem.decoder = ctx.decodeNull 269 | default: 270 | // Generic types: 271 | elem = ctx.getUniversalTagByKind(objType, opts) 272 | } 273 | 274 | // Check options for universal types 275 | if opts.set { 276 | if elem.tag != tagSequence { 277 | err = syntaxError( 278 | "'set' cannot be used with Go type '%s'", objType) 279 | } 280 | elem.tag = tagSet 281 | } 282 | return 283 | } 284 | 285 | // getUniversalTagByKind uses type kind to defined the decoder. 286 | func (ctx *Context) getUniversalTagByKind(objType reflect.Type, opts *fieldOptions) (elem expectedElement) { 287 | 288 | switch objType.Kind() { 289 | case reflect.Bool: 290 | elem.tag = tagBoolean 291 | elem.decoder = ctx.decodeBool 292 | 293 | case reflect.String: 294 | elem.tag = tagOctetString 295 | elem.decoder = ctx.decodeString 296 | 297 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 298 | elem.tag = tagInteger 299 | elem.decoder = ctx.decodeInt 300 | 301 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 302 | elem.tag = tagInteger 303 | elem.decoder = ctx.decodeUint 304 | 305 | case reflect.Struct: 306 | elem.tag = tagSequence 307 | elem.decoder = ctx.decodeStruct 308 | if opts.set { 309 | elem.decoder = ctx.decodeStructAsSet 310 | } 311 | 312 | case reflect.Array: 313 | if objType.Elem().Kind() == reflect.Uint8 { 314 | elem.tag = tagOctetString 315 | elem.decoder = ctx.decodeOctetString 316 | } else { 317 | elem.tag = tagSequence 318 | elem.decoder = ctx.decodeArray 319 | } 320 | 321 | case reflect.Slice: 322 | if objType.Elem().Kind() == reflect.Uint8 { 323 | elem.tag = tagOctetString 324 | elem.decoder = ctx.decodeOctetString 325 | } else { 326 | elem.tag = tagSequence 327 | elem.decoder = ctx.decodeSlice 328 | } 329 | } 330 | return 331 | } 332 | 333 | // 334 | func (ctx *Context) getExpectedFieldElements(value reflect.Value) ([]expectedFieldElement, error) { 335 | expectedValues := []expectedFieldElement{} 336 | for i := 0; i < value.NumField(); i++ { 337 | if value.CanSet() { 338 | // Get field and options 339 | field := value.Field(i) 340 | opts, err := parseOptions(value.Type().Field(i).Tag.Get(tagKey)) 341 | if err != nil { 342 | return nil, err 343 | } 344 | // Expand choices 345 | raw := &rawValue{} 346 | if opts.choice == nil { 347 | elem, err := ctx.getExpectedElement(raw, field.Type(), opts) 348 | if err != nil { 349 | return nil, err 350 | } 351 | expectedValues = append(expectedValues, 352 | expectedFieldElement{elem, field, opts}) 353 | } else { 354 | entries, err := ctx.getChoices(*opts.choice) 355 | if err != nil { 356 | return nil, err 357 | } 358 | for _, entry := range entries { 359 | raw.Class = entry.class 360 | raw.Tag = entry.tag 361 | elem, err := ctx.getExpectedElement(raw, field.Type(), opts) 362 | if err != nil { 363 | return nil, err 364 | } 365 | expectedValues = append(expectedValues, 366 | expectedFieldElement{elem, field, opts}) 367 | } 368 | } 369 | } 370 | } 371 | return expectedValues, nil 372 | } 373 | 374 | // getRawValuesFromBytes reads up to max values from the byte sequence. 375 | func (ctx *Context) getRawValuesFromBytes(data []byte, max int) ([]*rawValue, error) { 376 | // Raw values 377 | rawValues := []*rawValue{} 378 | reader := bytes.NewBuffer(data) 379 | for i := 0; i < max; i++ { 380 | // Parse an Asn.1 element 381 | raw, err := decodeRawValue(reader) 382 | if err != nil { 383 | return nil, err 384 | } 385 | rawValues = append(rawValues, raw) 386 | if reader.Len() == 0 { 387 | return rawValues, nil 388 | } 389 | } 390 | return nil, parseError("too many items for Sequence") 391 | } 392 | 393 | // matchExpectedValues tries to decode a sequence of raw values based on the 394 | // expected elements. 395 | func (ctx *Context) matchExpectedValues(eValues []expectedFieldElement, rValues []*rawValue) error { 396 | // Try to match expected and raw values 397 | rIndex := 0 398 | for eIndex := 0; eIndex < len(eValues); eIndex++ { 399 | e := eValues[eIndex] 400 | // Using nil decoder to skip matched choices 401 | if e.decoder == nil { 402 | continue 403 | } 404 | 405 | missing := true 406 | if rIndex < len(rValues) { 407 | raw := rValues[rIndex] 408 | if e.class == raw.Class && e.tag == raw.Tag { 409 | err := e.decoder(raw.Content, e.value) 410 | if err != nil { 411 | return err 412 | } 413 | // Mark as found and advance raw values index 414 | missing = false 415 | rIndex++ 416 | // Remove other options for the matched choice 417 | if e.opts.choice != nil { 418 | for i := eIndex + 1; i < len(eValues); i++ { 419 | c := eValues[i].opts.choice 420 | if c != nil && *c == *e.opts.choice { 421 | eValues[i].decoder = nil 422 | } 423 | } 424 | } 425 | } 426 | } 427 | 428 | if missing { 429 | if err := ctx.setMissingFieldValue(e); err != nil { 430 | return err 431 | } 432 | } 433 | } 434 | return nil 435 | } 436 | 437 | // setMissingFieldValue uses opts values to set the default value. 438 | func (ctx *Context) setMissingFieldValue(e expectedFieldElement) error { 439 | if e.opts.optional || e.opts.choice != nil { 440 | return nil 441 | } 442 | if e.opts.defaultValue != nil { 443 | err := ctx.setDefaultValue(e.value, e.opts) 444 | if err != nil { 445 | return err 446 | } 447 | return nil 448 | } 449 | return parseError("missing value for [%d %d]", e.class, e.tag) 450 | } 451 | 452 | // decodeStruct decodes struct fields in order 453 | func (ctx *Context) decodeStruct(data []byte, value reflect.Value) error { 454 | 455 | expectedValues, err := ctx.getExpectedFieldElements(value) 456 | if err != nil { 457 | return err 458 | } 459 | 460 | rawValues, err := ctx.getRawValuesFromBytes(data, len(expectedValues)) 461 | if err != nil { 462 | return err 463 | } 464 | 465 | return ctx.matchExpectedValues(expectedValues, rawValues) 466 | } 467 | 468 | // Decode a struct as an Asn.1 Set. 469 | // 470 | // The order doesn't matter for set. However DER dictates that a Set should be 471 | // encoded in the ascending order of the tags. So when decoding with DER, we 472 | // simply do not sort the raw values and use them in their natural order. 473 | func (ctx *Context) decodeStructAsSet(data []byte, value reflect.Value) error { 474 | 475 | // Get the expected values 476 | expectedElements, err := ctx.getExpectedFieldElements(value) 477 | if err != nil { 478 | return err 479 | } 480 | sort.Sort(expectedFieldElementSlice(expectedElements)) 481 | 482 | // Check duplicated tags 483 | for i := 1; i < len(expectedElements); i++ { 484 | curr := expectedElements[i] 485 | prev := expectedElements[i-1] 486 | if curr.class == prev.class && 487 | curr.tag == prev.tag { 488 | return syntaxError("duplicated tag (%d,%d)", curr.class, curr.tag) 489 | } 490 | } 491 | 492 | // Get the raw values 493 | rawValues, err := ctx.getRawValuesFromBytes(data, len(expectedElements)) 494 | if err != nil { 495 | return err 496 | } 497 | if !ctx.der.decoding { 498 | sort.Sort(rawValueSlice(rawValues)) 499 | } 500 | 501 | return ctx.matchExpectedValues(expectedElements, rawValues) 502 | } 503 | 504 | // decodeSlice decodes a SET(OF) as a slice 505 | func (ctx *Context) decodeSlice(data []byte, value reflect.Value) error { 506 | slice := reflect.New(value.Type()).Elem() 507 | var err error 508 | for len(data) > 0 { 509 | elem := reflect.New(value.Type().Elem()).Elem() 510 | data, err = ctx.DecodeWithOptions(data, elem.Addr().Interface(), "") 511 | if err != nil { 512 | return err 513 | } 514 | slice.Set(reflect.Append(slice, elem)) 515 | } 516 | value.Set(slice) 517 | return nil 518 | } 519 | 520 | // decodeArray decodes a SET(OF) as an array 521 | func (ctx *Context) decodeArray(data []byte, value reflect.Value) error { 522 | var err error 523 | for i := 0; i < value.Len(); i++ { 524 | if len(data) == 0 { 525 | return parseError("missing elements") 526 | } 527 | elem := reflect.New(value.Type().Elem()).Elem() 528 | data, err = ctx.DecodeWithOptions(data, elem.Addr().Interface(), "") 529 | if err != nil { 530 | return err 531 | } 532 | value.Index(i).Set(elem) 533 | } 534 | if len(data) > 0 { 535 | return parseError("too many elements") 536 | } 537 | return nil 538 | } 539 | -------------------------------------------------------------------------------- /encode.go: -------------------------------------------------------------------------------- 1 | package asn1 2 | 3 | import ( 4 | "reflect" 5 | "sort" 6 | "unicode" 7 | ) 8 | 9 | // Encode returns the ASN.1 encoding of obj. 10 | // 11 | // See (*Context).EncodeWithOptions() for further details. 12 | func (ctx *Context) Encode(obj interface{}) (data []byte, err error) { 13 | return ctx.EncodeWithOptions(obj, "") 14 | } 15 | 16 | // EncodeWithOptions returns the ASN.1 encoding of obj using additional options. 17 | // 18 | // See (*Context).DecodeWithOptions() for further details regarding types and 19 | // options. 20 | func (ctx *Context) EncodeWithOptions(obj interface{}, options string) (data []byte, err error) { 21 | 22 | opts, err := parseOptions(options) 23 | if err != nil { 24 | return nil, err 25 | } 26 | 27 | value := reflect.ValueOf(obj) 28 | raw, err := ctx.encode(value, opts) 29 | if err != nil { 30 | return 31 | } 32 | data, err = raw.encode() 33 | return 34 | } 35 | 36 | // Main encode function 37 | func (ctx *Context) encode(value reflect.Value, opts *fieldOptions) (*rawValue, error) { 38 | 39 | // Skip the interface type 40 | switch value.Kind() { 41 | case reflect.Interface: 42 | value = value.Elem() 43 | } 44 | 45 | // If a value is missing the default value is used 46 | empty := isEmpty(value) 47 | if opts.defaultValue != nil { 48 | if empty && !ctx.der.encoding { 49 | defaultValue, err := ctx.newDefaultValue(value.Type(), opts) 50 | if err != nil { 51 | return nil, err 52 | } 53 | value = defaultValue 54 | empty = false 55 | } 56 | } 57 | 58 | // Encode data 59 | raw, err := ctx.encodeValue(value, opts) 60 | if err != nil { 61 | return nil, err 62 | } 63 | 64 | // Since the empty flag is already calculated, check if it's optional 65 | if (opts.optional || opts.defaultValue != nil) && empty { 66 | return nil, nil 67 | } 68 | 69 | // Modify the data generated based on the given tags 70 | raw, err = ctx.applyOptions(value, raw, opts) 71 | if err != nil { 72 | return nil, err 73 | } 74 | 75 | return raw, nil 76 | } 77 | 78 | func (ctx *Context) encodeValue(value reflect.Value, opts *fieldOptions) (raw *rawValue, err error) { 79 | 80 | raw = &rawValue{} 81 | encoder := encoderFunction(nil) 82 | 83 | // Special types: 84 | objType := value.Type() 85 | switch objType { 86 | case bigIntType: 87 | raw.Tag = tagInteger 88 | encoder = ctx.encodeBigInt 89 | case oidType: 90 | raw.Tag = tagOid 91 | encoder = ctx.encodeOid 92 | case nullType: 93 | raw.Tag = tagNull 94 | encoder = ctx.encodeNull 95 | } 96 | 97 | if encoder == nil { 98 | // Generic types: 99 | switch value.Kind() { 100 | case reflect.Bool: 101 | raw.Tag = tagBoolean 102 | encoder = ctx.encodeBool 103 | 104 | case reflect.String: 105 | raw.Tag = tagOctetString 106 | encoder = ctx.encodeString 107 | 108 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 109 | raw.Tag = tagInteger 110 | encoder = ctx.encodeInt 111 | 112 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 113 | raw.Tag = tagInteger 114 | encoder = ctx.encodeUint 115 | 116 | case reflect.Struct: 117 | raw.Tag = tagSequence 118 | raw.Constructed = true 119 | encoder = ctx.encodeStruct 120 | if opts.set { 121 | encoder = ctx.encodeStructAsSet 122 | } 123 | 124 | case reflect.Array, reflect.Slice: 125 | if objType.Elem().Kind() == reflect.Uint8 { 126 | raw.Tag = tagOctetString 127 | encoder = ctx.encodeOctetString 128 | } else { 129 | raw.Tag = tagSequence 130 | raw.Constructed = true 131 | encoder = ctx.encodeSlice 132 | } 133 | } 134 | } 135 | 136 | if encoder == nil { 137 | return nil, syntaxError("invalid Go type: %s", value.Type()) 138 | } 139 | raw.Content, err = encoder(value) 140 | return 141 | } 142 | 143 | // applyOptions modifies a raw value based on the given options. 144 | func (ctx *Context) applyOptions(value reflect.Value, raw *rawValue, opts *fieldOptions) (*rawValue, error) { 145 | 146 | // Change sequence to set 147 | if opts.set { 148 | if raw.Class != classUniversal || raw.Tag != tagSequence { 149 | return nil, syntaxError("Go type '%s' does not accept the flag 'set'", value.Type()) 150 | } 151 | raw.Tag = tagSet 152 | } 153 | 154 | // Check if this type is an Asn.1 choice 155 | if opts.choice != nil { 156 | entry, err := ctx.getChoiceByType(*opts.choice, value.Type()) 157 | if err != nil { 158 | return nil, err 159 | } 160 | raw, err = ctx.applyOptions(value, raw, entry.opts) 161 | raw.Class = entry.class 162 | raw.Tag = entry.tag 163 | } 164 | 165 | // Add an enclosing tag 166 | if opts.explicit { 167 | if opts.tag == nil { 168 | return nil, syntaxError( 169 | "invalid flag 'explicit' without tag on Go type '%s'", 170 | value.Type()) 171 | } 172 | content, err := raw.encode() 173 | if err != nil { 174 | return nil, err 175 | } 176 | raw = &rawValue{} 177 | raw.Constructed = true 178 | raw.Content = content 179 | } 180 | 181 | // Change tag 182 | if opts.tag != nil { 183 | raw.Class = classContextSpecific 184 | raw.Tag = uint(*opts.tag) 185 | } 186 | // Change class 187 | if opts.universal { 188 | raw.Class = classUniversal 189 | } 190 | if opts.application { 191 | raw.Class = classApplication 192 | } 193 | 194 | // Use the indefinite length encoding 195 | if opts.indefinite { 196 | if !raw.Constructed { 197 | return nil, syntaxError( 198 | "invalid flag 'indefinite' on Go type: %s", 199 | value.Type()) 200 | } 201 | raw.Indefinite = true 202 | } 203 | 204 | return raw, nil 205 | } 206 | 207 | // isEmpty checks is a value is empty. 208 | func isEmpty(value reflect.Value) bool { 209 | defaultValue := reflect.Zero(value.Type()) 210 | return reflect.DeepEqual(value.Interface(), defaultValue.Interface()) 211 | } 212 | 213 | // isFieldExported checks is the field name starts with a capital letter. 214 | func isFieldExported(field reflect.StructField) bool { 215 | return unicode.IsUpper([]rune(field.Name)[0]) 216 | } 217 | 218 | // getRawValuesFromFields encodes each valid field ofa struct value and returns 219 | // a slice of raw values. 220 | func (ctx *Context) getRawValuesFromFields(value reflect.Value) ([]*rawValue, error) { 221 | // Encode each child to a raw value 222 | children := []*rawValue{} 223 | for i := 0; i < value.NumField(); i++ { 224 | fieldValue := value.Field(i) 225 | fieldStruct := value.Type().Field(i) 226 | // Ignore field that are not exported (that starts with lowercase) 227 | if isFieldExported(fieldStruct) { 228 | tag := fieldStruct.Tag.Get(tagKey) 229 | opts, err := parseOptions(tag) 230 | if err != nil { 231 | return nil, err 232 | } 233 | raw, err := ctx.encode(fieldValue, opts) 234 | if err != nil { 235 | return nil, err 236 | } 237 | children = append(children, raw) 238 | } 239 | } 240 | return children, nil 241 | } 242 | 243 | // encodeRawValues is a helper function to encode raw value in sequence. 244 | func (ctx *Context) encodeRawValues(values ...*rawValue) ([]byte, error) { 245 | content := []byte{} 246 | for _, raw := range values { 247 | buf, err := raw.encode() 248 | if err != nil { 249 | return nil, err 250 | } 251 | content = append(content, buf...) 252 | } 253 | return content, nil 254 | } 255 | 256 | // encodeStruct encodes structs fields in order. 257 | func (ctx *Context) encodeStruct(value reflect.Value) ([]byte, error) { 258 | // Encode each child to a raw value 259 | children, err := ctx.getRawValuesFromFields(value) 260 | if err != nil { 261 | return nil, err 262 | } 263 | return ctx.encodeRawValues(children...) 264 | } 265 | 266 | // encodeStructAsSet works similarly to encodeStruct, but in Der mode the 267 | // fields are encoded in ascending order of their tags. 268 | func (ctx *Context) encodeStructAsSet(value reflect.Value) ([]byte, error) { 269 | // Encode each child to a raw value 270 | children, err := ctx.getRawValuesFromFields(value) 271 | if err != nil { 272 | return nil, err 273 | } 274 | // Sort if necessary 275 | if ctx.der.encoding { 276 | sort.Sort(rawValueSlice(children)) 277 | } 278 | return ctx.encodeRawValues(children...) 279 | } 280 | 281 | // encodeSlice encodes a slice or array as a sequence of values. 282 | func (ctx *Context) encodeSlice(value reflect.Value) ([]byte, error) { 283 | content := []byte{} 284 | for i := 0; i < value.Len(); i++ { 285 | itemValue := value.Index(i) 286 | childBytes, err := ctx.EncodeWithOptions(itemValue.Interface(), "") 287 | if err != nil { 288 | return nil, err 289 | } 290 | content = append(content, childBytes...) 291 | } 292 | return content, nil 293 | } 294 | -------------------------------------------------------------------------------- /example_test.go: -------------------------------------------------------------------------------- 1 | package asn1_test 2 | 3 | import ( 4 | "log" 5 | "reflect" 6 | 7 | "github.com/PromonLogicalis/asn1" 8 | ) 9 | 10 | func Example() { 11 | ctx := asn1.NewContext() 12 | 13 | // Use BER for encoding and decoding. 14 | ctx.SetDer(false, false) 15 | 16 | // Add a CHOICE 17 | ctx.AddChoice("value", []asn1.Choice{ 18 | { 19 | Type: reflect.TypeOf(""), 20 | Options: "tag:0", 21 | }, 22 | { 23 | Type: reflect.TypeOf(int(0)), 24 | Options: "tag:1", 25 | }, 26 | }) 27 | 28 | type Message struct { 29 | Id int 30 | Value interface{} `asn1:"choice:value"` 31 | } 32 | 33 | // Encode 34 | msg := Message{ 35 | Id: 1000, 36 | Value: "this is a value", 37 | } 38 | data, err := ctx.Encode(msg) 39 | if err != nil { 40 | log.Fatal(err) 41 | } 42 | 43 | // Decode 44 | decodedMsg := Message{} 45 | _, err = ctx.Decode(data, &decodedMsg) 46 | if err != nil { 47 | log.Fatal(err) 48 | } 49 | 50 | log.Printf("%+v\n", decodedMsg) 51 | } 52 | -------------------------------------------------------------------------------- /gen_readme.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Add badges: 4 | cat > ./README.md << 'EOF' 5 | [![Build Status](https://travis-ci.org/PromonLogicalis/asn1.svg?branch=master)](https://travis-ci.org/PromonLogicalis/asn1) [![Go Report Card](https://goreportcard.com/badge/github.com/PromonLogicalis/asn1)](https://goreportcard.com/report/github.com/PromonLogicalis/asn1) [![GoDoc](https://godoc.org/github.com/PromonLogicalis/asn1?status.svg)](https://godoc.org/github.com/PromonLogicalis/asn1) 6 | EOF 7 | 8 | # Add Go doc 9 | godocdown ./ >> ./README.md 10 | -------------------------------------------------------------------------------- /options.go: -------------------------------------------------------------------------------- 1 | package asn1 2 | 3 | import ( 4 | "strconv" 5 | "strings" 6 | ) 7 | 8 | type fieldOptions struct { 9 | universal bool 10 | application bool 11 | explicit bool 12 | indefinite bool 13 | optional bool 14 | set bool 15 | tag *int 16 | defaultValue *int 17 | choice *string 18 | } 19 | 20 | // validate returns an error if any option is invalid. 21 | func (opts *fieldOptions) validate() error { 22 | tagError := func(class string) error { 23 | return syntaxError( 24 | "'tag' must be specified when '%s' is used", class) 25 | } 26 | if opts.universal && opts.tag == nil { 27 | return tagError("universal") 28 | } 29 | if opts.application && opts.tag == nil { 30 | return tagError("application") 31 | } 32 | if opts.tag != nil && *opts.tag < 0 { 33 | return syntaxError("'tag' cannot be negative: %d", *opts.tag) 34 | } 35 | if opts.choice != nil && *opts.choice == "" { 36 | return syntaxError("'choice' cannot be empty") 37 | } 38 | return nil 39 | } 40 | 41 | // parseOption returns a parsed fieldOptions or an error. 42 | func parseOptions(s string) (*fieldOptions, error) { 43 | var opts fieldOptions 44 | for _, token := range strings.Split(s, ",") { 45 | args := strings.Split(strings.TrimSpace(token), ":") 46 | err := parseOption(&opts, args) 47 | if err != nil { 48 | return nil, err 49 | } 50 | } 51 | if err := opts.validate(); err != nil { 52 | return nil, err 53 | } 54 | return &opts, nil 55 | } 56 | 57 | // parseOption parse a single option. 58 | func parseOption(opts *fieldOptions, args []string) error { 59 | var err error 60 | switch args[0] { 61 | case "": 62 | // ignore 63 | 64 | case "universal": 65 | opts.universal, err = parseBoolOption(args) 66 | 67 | case "application": 68 | opts.application, err = parseBoolOption(args) 69 | 70 | case "explicit": 71 | opts.explicit, err = parseBoolOption(args) 72 | 73 | case "indefinite": 74 | opts.indefinite, err = parseBoolOption(args) 75 | 76 | case "optional": 77 | opts.optional, err = parseBoolOption(args) 78 | 79 | case "set": 80 | opts.set, err = parseBoolOption(args) 81 | 82 | case "tag": 83 | opts.tag, err = parseIntOption(args) 84 | 85 | case "default": 86 | opts.defaultValue, err = parseIntOption(args) 87 | 88 | case "choice": 89 | opts.choice, err = parseStringOption(args) 90 | 91 | default: 92 | err = syntaxError("Invalid option: %s", args[0]) 93 | } 94 | return err 95 | } 96 | 97 | // parseBoolOption just checks if no arguments were given. 98 | func parseBoolOption(args []string) (bool, error) { 99 | if len(args) > 1 { 100 | return false, syntaxError("option '%s' does not have arguments.", 101 | args[0]) 102 | } 103 | return true, nil 104 | } 105 | 106 | // parseIntOption parses an integer argument. 107 | func parseIntOption(args []string) (*int, error) { 108 | if len(args) != 2 { 109 | return nil, syntaxError("option '%s' does not have arguments.") 110 | } 111 | num, err := strconv.Atoi(args[1]) 112 | if err != nil { 113 | return nil, syntaxError("invalid value '%s' for option '%s'.", 114 | args[1], args[0]) 115 | } 116 | return &num, nil 117 | } 118 | 119 | // parseStringOption parses a string argument. 120 | func parseStringOption(args []string) (*string, error) { 121 | if len(args) != 2 { 122 | return nil, syntaxError("option '%s' does not have arguments.") 123 | } 124 | return &args[1], nil 125 | } 126 | -------------------------------------------------------------------------------- /raw.go: -------------------------------------------------------------------------------- 1 | package asn1 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "io/ioutil" 7 | "strconv" 8 | ) 9 | 10 | // ASN.1 class tags. 11 | const ( 12 | classUniversal = 0x00 13 | classApplication = 0x01 14 | classContextSpecific = 0x02 15 | classPrivate = 0x03 16 | ) 17 | 18 | // ASN.1 universal tag numbers. 19 | const ( 20 | tagEoc = 0x00 21 | tagBoolean = 0x01 22 | tagInteger = 0x02 23 | tagBitString = 0x03 24 | tagOctetString = 0x04 25 | tagNull = 0x05 26 | tagOid = 0x06 27 | tagSequence = 0x10 28 | tagSet = 0x11 29 | tagPrintableString = 0x13 30 | tagT61String = 0x14 31 | tagIA5String = 0x16 32 | tagUtcTime = 0x17 33 | ) 34 | 35 | // Internal consts 36 | const ( 37 | intBits = strconv.IntSize 38 | intBytes = intBits / 8 39 | ) 40 | 41 | type rawValue struct { 42 | Class uint 43 | Tag uint 44 | Constructed bool 45 | Indefinite bool 46 | Content []byte 47 | } 48 | 49 | func (raw *rawValue) encode() ([]byte, error) { 50 | 51 | if raw == nil { 52 | return []byte{}, nil 53 | } 54 | 55 | buf, err := encodeIdentifier(raw) 56 | if err != nil { 57 | return nil, err 58 | } 59 | 60 | // Add length information and raw data 61 | if !raw.Indefinite { 62 | length := uint(len(raw.Content)) 63 | buf = append(buf, encodeLength(length)...) 64 | buf = append(buf, raw.Content...) 65 | } else { 66 | // Indefinite length uses 0x80, data..., 0x00, 0x00 67 | if !raw.Constructed { 68 | return nil, syntaxError("indefinite length is only allowed to constructed types") 69 | } 70 | buf = append(buf, 0x80) 71 | buf = append(buf, raw.Content...) 72 | buf = append(buf, 0x00, 0x00) 73 | } 74 | 75 | return buf, nil 76 | } 77 | 78 | func encodeIdentifier(node *rawValue) ([]byte, error) { 79 | 80 | if node.Class > 0x03 { 81 | return nil, syntaxError("invalid class value: %d", node.Class) 82 | } 83 | 84 | identifier := []byte{0x00} 85 | 86 | // Class (bits 7 and 6) + primitive/constructed (1 bit) + tag (5 bits) 87 | identifier[0] += byte((node.Class & 0x03) << 6) 88 | 89 | // Primitive/constructed (bit 5) 90 | if node.Constructed { 91 | identifier[0] += byte(1 << 5) 92 | } 93 | 94 | // Tag (bits 4 to 0) 95 | if node.Tag <= 30 { 96 | identifier[0] += byte(0x1f & node.Tag) 97 | } else { 98 | identifier[0] += 0x1f 99 | identifier = append(identifier, encodeMultiByteTag(node.Tag)...) 100 | } 101 | return identifier, nil 102 | } 103 | 104 | func encodeMultiByteTag(tag uint) []byte { 105 | 106 | // A tag is encoded in a big endian sequence of octets each one holding a 7 bit value. 107 | // The most significant bit of each octet must be 1, with the exception of the last octet that must be zero. 108 | // Example: 1xxxxxxx 1xxxxxxx ... 0xxxxxxx 109 | 110 | // An int32 needs 5 octets and an int64 needs 10: 111 | bufLen := (intBits-1)/7 + 1 112 | buf := make([]byte, bufLen) 113 | 114 | for i := range buf { 115 | shift := uint(7 * (len(buf) - i - 1)) 116 | mask := uint(0x7f << shift) 117 | buf[i] = byte((tag & mask) >> shift) 118 | // Only the last byte is not marked with 0x80 119 | if i != len(buf)-1 { 120 | buf[i] |= 0x80 121 | } 122 | } 123 | // Discard leading zero values 124 | return removeLeadingBytes(buf, 0x80) 125 | } 126 | 127 | func encodeLength(length uint) []byte { 128 | 129 | // The first bit indicates if length is encoded in a single byte 130 | if length < 0x80 { 131 | return []byte{byte(length)} 132 | } 133 | 134 | // Multi byte length follow the rules: 135 | // - First byte: 0x80 + N (number of following bytes where length is encoded). 136 | // - N bytes 137 | 138 | // A byte slice length is an int. So we just need at most 4 bytes 139 | buf := make([]byte, intBytes) 140 | for i := range buf { 141 | shift := uint((intBytes - i - 1) * 8) 142 | mask := uint(0xff << shift) 143 | buf[i] = byte((mask & length) >> shift) 144 | } 145 | 146 | // Ignore leading zeros 147 | buf = removeLeadingBytes(buf, 0x00) 148 | 149 | // Add leading byte with the number of following bytes 150 | buf = append([]byte{0x80 + byte(len(buf))}, buf...) 151 | return buf 152 | } 153 | 154 | func removeLeadingBytes(buf []byte, target byte) []byte { 155 | start := 0 156 | for start < len(buf)-1 && buf[start] == target { 157 | start++ 158 | } 159 | return buf[start:] 160 | } 161 | 162 | func decodeRawValue(reader io.Reader) (*rawValue, error) { 163 | 164 | class, tag, constructed, err := decodeIdentifier(reader) 165 | if err != nil { 166 | return nil, err 167 | } 168 | 169 | length, indefinite, err := decodeLength(reader) 170 | if err != nil { 171 | return nil, err 172 | } 173 | if indefinite && !constructed { 174 | return nil, parseError("primitive node with indefinite length") 175 | } 176 | 177 | // Indefinite form 178 | var content []byte 179 | if !indefinite { 180 | content = make([]byte, length) 181 | _, err = io.ReadFull(reader, content) 182 | if err != nil { 183 | return nil, err 184 | } 185 | } else { 186 | buffer := bytes.NewBuffer([]byte{}) 187 | childrenReader := io.TeeReader(reader, buffer) 188 | err := readEoc(childrenReader) 189 | if err != nil { 190 | return nil, err 191 | } 192 | // At this point, buffer also contains the EoC bytes 193 | content = buffer.Bytes() 194 | content = content[:len(content)-2] 195 | } 196 | 197 | raw := rawValue{class, tag, constructed, indefinite, content} 198 | return &raw, nil 199 | } 200 | 201 | func readEoc(reader io.Reader) error { 202 | 203 | for { 204 | class, tag, constructed, err := decodeIdentifier(reader) 205 | if err != nil { 206 | return err 207 | } 208 | 209 | length, indefinite, err := decodeLength(reader) 210 | if err != nil { 211 | return err 212 | } 213 | 214 | if indefinite && !constructed { 215 | return parseError("primitive node with indefinite length") 216 | } 217 | 218 | if class == 0 && tag == 0 && indefinite == false && length == 0 { 219 | break 220 | } 221 | 222 | if indefinite { 223 | err = readEoc(reader) 224 | } else { 225 | err = skipBytes(reader, int64(length)) 226 | } 227 | if err != nil { 228 | return err 229 | } 230 | } 231 | return nil 232 | } 233 | 234 | func decodeMultiByteTag(reader io.Reader) (uint, error) { 235 | // Tag is encoded in one or more following bytes 236 | tag := uint(0) 237 | for { 238 | // Read a byte 239 | b, err := readByte(reader) 240 | if err != nil { 241 | return 0, err 242 | } 243 | // if we need to shift out non zeros bits, so the tag is too big for an uint 244 | msb := uint64(0xfe) << (intBits - 8) // 7 most significant bits 245 | if uint64(tag)&msb != 0 { 246 | return 0, parseError("multi byte tag too big") 247 | } 248 | // Shift the previous value and add the new 7 bits 249 | tag = (tag << 7) | uint(b&0x7f) 250 | // The last byte is indicated by the most significant bit equals to zero 251 | if b&0x80 == 0 { 252 | break 253 | } 254 | } 255 | return tag, nil 256 | } 257 | 258 | func decodeIdentifier(reader io.Reader) (class uint, tag uint, constructed bool, err error) { 259 | 260 | b, err := readByte(reader) 261 | if err != nil { 262 | return 263 | } 264 | 265 | // Read class and constructed flag 266 | class = uint((b & 0xc0) >> 6) 267 | if b&0x20 != 0 { 268 | constructed = true 269 | } 270 | 271 | // Read the tag number 272 | tag = uint(b & 0x1f) 273 | if tag == 0x1f { 274 | // Tag is encoded in one or more following bytes 275 | tag, err = decodeMultiByteTag(reader) 276 | if err != nil { 277 | return 278 | } 279 | } 280 | return 281 | } 282 | 283 | func decodeLength(reader io.Reader) (length uint, indefinite bool, err error) { 284 | 285 | // Read length 286 | b, err := readByte(reader) 287 | if err != nil { 288 | return 289 | } 290 | 291 | // Short form 292 | if b&0x80 == 0 { 293 | length = uint(b) 294 | return 295 | } 296 | 297 | // Indefinite form 298 | if b == 0x80 { 299 | indefinite = true 300 | return 301 | } 302 | 303 | // Long form 304 | if b == 0xff { 305 | err = parseError("invalid number of length octets: %x", b) 306 | return 307 | } 308 | octets := make([]byte, int(b&0x7f)) 309 | _, err = io.ReadFull(reader, octets) 310 | if err != nil { 311 | return 312 | } 313 | for _, b = range octets { 314 | msb := uint64(0xff) << (intBits - 8) 315 | if uint64(length)&msb != 0 { 316 | err = parseError("multi byte length too big") 317 | return 318 | } 319 | length = (length << 8) | uint(b) 320 | } 321 | 322 | return 323 | } 324 | 325 | func readByte(reader io.Reader) (byte, error) { 326 | buf := []byte{0x00} 327 | _, err := io.ReadFull(reader, buf) 328 | return buf[0], err 329 | } 330 | 331 | func skipBytes(reader io.Reader, count int64) error { 332 | _, err := io.CopyN(ioutil.Discard, reader, count) 333 | return err 334 | } 335 | -------------------------------------------------------------------------------- /sort.go: -------------------------------------------------------------------------------- 1 | package asn1 2 | 3 | import "sort" 4 | 5 | // isTagLessThan compares two tags (class + tag number) 6 | // TODO: maybe a common Tag type can simplify that. 7 | func isTagLessThan(c1, t1, c2, t2 uint) bool { 8 | if c1 == c2 { 9 | return t1 < t2 10 | } 11 | return c1 < c2 12 | } 13 | 14 | // rawValueSlice is a helper type to sort an slice of RawValues 15 | type rawValueSlice []*rawValue 16 | 17 | var _ sort.Interface = rawValueSlice{} 18 | 19 | func (s rawValueSlice) Len() int { return len(s) } 20 | func (s rawValueSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 21 | func (s rawValueSlice) Less(i, j int) bool { 22 | return isTagLessThan(s[i].Class, s[i].Tag, s[j].Class, s[j].Tag) 23 | } 24 | 25 | // expectedFieldElementSlice is a helper type to sort an slice of expectedFieldElement 26 | type expectedFieldElementSlice []expectedFieldElement 27 | 28 | var _ sort.Interface = expectedFieldElementSlice{} 29 | 30 | func (s expectedFieldElementSlice) Len() int { return len(s) } 31 | func (s expectedFieldElementSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 32 | func (s expectedFieldElementSlice) Less(i, j int) bool { 33 | return isTagLessThan(s[i].class, s[i].tag, s[j].class, s[j].tag) 34 | } 35 | -------------------------------------------------------------------------------- /types.go: -------------------------------------------------------------------------------- 1 | package asn1 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | "reflect" 8 | ) 9 | 10 | // Pre-calculated types for convenience 11 | var ( 12 | bigIntType = reflect.TypeOf((*big.Int)(nil)) 13 | oidType = reflect.TypeOf(Oid{}) 14 | nullType = reflect.TypeOf(Null{}) 15 | ) 16 | 17 | /* 18 | * Basic encoders and decoders 19 | */ 20 | 21 | // A function that encodes data. 22 | type encoderFunction func(reflect.Value) ([]byte, error) 23 | 24 | // A function that decodes data. 25 | type decoderFunction func([]byte, reflect.Value) error 26 | 27 | func (ctx *Context) encodeBool(value reflect.Value) ([]byte, error) { 28 | if value.Kind() != reflect.Bool { 29 | return nil, wrongType(reflect.Bool.String(), value) 30 | } 31 | if value.Bool() { 32 | return []byte{0xff}, nil 33 | } 34 | return []byte{0x00}, nil 35 | } 36 | 37 | func (ctx *Context) decodeBool(data []byte, value reflect.Value) error { 38 | // TODO check value type 39 | if !ctx.der.decoding { 40 | boolValue := parseBigInt(data).Cmp(big.NewInt(0)) != 0 41 | value.SetBool(boolValue) 42 | return nil 43 | } 44 | 45 | // DER is more restrict regarding valid booleans 46 | if len(data) == 1 { 47 | switch data[0] { 48 | case 0x00: 49 | value.SetBool(false) 50 | return nil 51 | case 0xff: 52 | value.SetBool(true) 53 | return nil 54 | } 55 | } 56 | return parseError("invalid bool value") 57 | } 58 | 59 | func (ctx *Context) encodeBigInt(value reflect.Value) ([]byte, error) { 60 | num, ok := value.Interface().(*big.Int) 61 | if !ok { 62 | return nil, wrongType(bigIntType.String(), value) 63 | } 64 | if num == nil { 65 | return []byte{0x00}, nil 66 | } 67 | var buf []byte 68 | if num.Sign() >= 0 { 69 | buf = append([]byte{0x00}, num.Bytes()...) 70 | } else { 71 | // Set absolute value 72 | convertedNum := big.NewInt(0) 73 | convertedNum.Abs(num) 74 | // Subtract One 75 | convertedNum.Sub(convertedNum, big.NewInt(1)) 76 | // Invert bytes 77 | buf = convertedNum.Bytes() 78 | for i, b := range buf { 79 | buf[i] = ^b 80 | } 81 | buf = append([]byte{0xff}, buf...) 82 | } 83 | return removeIntLeadingBytes(buf), nil 84 | } 85 | 86 | func (ctx *Context) decodeBigInt(data []byte, value reflect.Value) error { 87 | // TODO check value type 88 | err := checkInt(ctx, data) 89 | if err != nil { 90 | return err 91 | } 92 | i := parseBigInt(data) 93 | value.Set(reflect.ValueOf(i)) 94 | return nil 95 | } 96 | 97 | func (ctx *Context) encodeInt(value reflect.Value) ([]byte, error) { 98 | switch value.Kind() { 99 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 100 | default: 101 | return nil, wrongType("signed integer", value) 102 | } 103 | n := value.Int() 104 | buf := make([]byte, 8) 105 | for i := range buf { 106 | shift := 8 * uint(len(buf)-i-1) 107 | mask := int64(0xff) << shift 108 | buf[i] = byte((n & mask) >> shift) 109 | } 110 | return removeIntLeadingBytes(buf), nil 111 | } 112 | 113 | func (ctx *Context) decodeInt(data []byte, value reflect.Value) error { 114 | // TODO check value type 115 | err := checkInt(ctx, data) 116 | if err != nil { 117 | return err 118 | } 119 | if len(data) > 8 { 120 | return parseError("integer too large for Go type '%s'", value.Type()) 121 | } 122 | // Sign extend the value 123 | extensionByte := byte(0x00) 124 | if len(data) > 0 && data[0]&0x80 != 0 { 125 | extensionByte = byte(0xff) 126 | } 127 | extension := make([]byte, 8-len(data)) 128 | for i := range extension { 129 | extension[i] = extensionByte 130 | } 131 | data = append(extension, data...) 132 | // Decode binary 133 | num := int64(0) 134 | for i := 0; i < len(data); i++ { 135 | num <<= 8 136 | num |= int64(data[i]) 137 | } 138 | value.SetInt(num) 139 | return nil 140 | } 141 | 142 | func (ctx *Context) encodeUint(value reflect.Value) ([]byte, error) { 143 | switch value.Kind() { 144 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 145 | default: 146 | return nil, wrongType("unsigned integer", value) 147 | } 148 | n := value.Uint() 149 | buf := make([]byte, 9) 150 | for i := range buf { 151 | shift := 8 * uint(len(buf)-i-1) 152 | mask := uint64(0xff) << shift 153 | buf[i] = byte((n & mask) >> shift) 154 | } 155 | return removeIntLeadingBytes(buf), nil 156 | } 157 | 158 | func (ctx *Context) decodeUint(data []byte, value reflect.Value) error { 159 | // TODO check value type 160 | err := checkInt(ctx, data) 161 | if err != nil { 162 | return err 163 | } 164 | if len(data) > 8 { 165 | return parseError("integer too large for Go type '%s'", value.Type()) 166 | } 167 | if len(data) > 0 && data[0]&0x80 != 0 { 168 | return parseError("negative integer can't be assigned to Go type '%s'", value.Type()) 169 | } 170 | num := uint64(0) 171 | for i := 0; i < len(data); i++ { 172 | num <<= 8 173 | num |= uint64(data[i]) 174 | } 175 | value.SetUint(num) 176 | return nil 177 | } 178 | 179 | func (ctx *Context) encodeOctetString(value reflect.Value) ([]byte, error) { 180 | // Check type 181 | kind := value.Kind() 182 | if !(kind == reflect.Array || kind == reflect.Slice) && 183 | value.Type().Elem().Kind() == reflect.Uint8 { 184 | // Invalid type or element type 185 | return nil, wrongType("array or slice of bytes", value) 186 | } 187 | if kind == reflect.Slice { 188 | return value.Interface().([]byte), nil 189 | } 190 | data := make([]byte, value.Len()) 191 | for i := 0; i < value.Len(); i++ { 192 | data[i] = value.Index(i).Interface().(byte) 193 | } 194 | return data, nil 195 | } 196 | 197 | func (ctx *Context) decodeOctetString(data []byte, value reflect.Value) error { 198 | // Check type 199 | kind := value.Kind() 200 | if !(kind == reflect.Array || kind == reflect.Slice) && 201 | value.Type().Elem().Kind() == reflect.Uint8 { 202 | // Invalid type or element type 203 | return wrongType("array or slice of bytes", value) 204 | } 205 | if value.Kind() == reflect.Array { 206 | // Check array length 207 | if len(data) != value.Len() { 208 | t := fmt.Sprintf("[%d]uint8", value.Len()) 209 | return wrongType(t, value) 210 | } 211 | // Get reference to the array as a slice 212 | dest := value.Slice(0, value.Len()).Interface().([]byte) 213 | // Copy data 214 | copy(dest, data) 215 | } else { 216 | // Set value with a copy of the array data 217 | value.Set(reflect.ValueOf(append([]byte{}, data...))) 218 | } 219 | return nil 220 | } 221 | 222 | func (ctx *Context) encodeString(value reflect.Value) ([]byte, error) { 223 | if value.Kind() != reflect.String { 224 | return nil, wrongType(reflect.String.String(), value) 225 | } 226 | return []byte(value.String()), nil 227 | } 228 | 229 | func (ctx *Context) decodeString(data []byte, value reflect.Value) error { 230 | // TODO check value type 231 | s := string(data) 232 | value.SetString(s) 233 | return nil 234 | } 235 | 236 | /* 237 | * Custom types 238 | */ 239 | 240 | // Oid is used to encode and decode ASN.1 OBJECT IDENTIFIERs. 241 | type Oid []uint 242 | 243 | // Cmp returns zero if both Oids are the same, a negative value if oid 244 | // lexicographically precedes other and a positive value otherwise. 245 | func (oid Oid) Cmp(other Oid) int { 246 | for i, n := range oid { 247 | if i >= len(other) { 248 | return 1 249 | } 250 | if n != other[i] { 251 | return int(n) - int(other[i]) 252 | } 253 | } 254 | return len(oid) - len(other) 255 | } 256 | 257 | // String returns the dotted representation of oid. 258 | func (oid Oid) String() string { 259 | if len(oid) == 0 { 260 | return "" 261 | } 262 | s := fmt.Sprintf(".%d", oid[0]) 263 | for i := 1; i < len(oid); i++ { 264 | s += fmt.Sprintf(".%d", oid[i]) 265 | } 266 | return s 267 | } 268 | 269 | func (ctx *Context) encodeOid(value reflect.Value) ([]byte, error) { 270 | // Check values 271 | oid, ok := value.Interface().(Oid) 272 | if !ok { 273 | return nil, wrongType(oidType.String(), value) 274 | } 275 | 276 | value1 := uint(0) 277 | if len(oid) >= 1 { 278 | value1 = oid[0] 279 | if value1 > 2 { 280 | return nil, parseError("invalid value for first element of OID: %d", value1) 281 | } 282 | } 283 | 284 | value2 := uint(0) 285 | if len(oid) >= 2 { 286 | value2 = oid[1] 287 | if value2 > 39 { 288 | return nil, parseError("invalid value for first element of OID: %d", value2) 289 | } 290 | } 291 | 292 | bytes := []byte{byte(40*value1 + value2)} 293 | for i := 2; i < len(oid); i++ { 294 | bytes = append(bytes, encodeMultiByteTag(oid[i])...) 295 | } 296 | return bytes, nil 297 | } 298 | 299 | func (ctx *Context) decodeOid(data []byte, value reflect.Value) error { 300 | // TODO check value type 301 | if len(data) == 0 { 302 | value.Set(reflect.ValueOf(Oid{})) 303 | return nil 304 | } 305 | 306 | value1 := uint(data[0] / 40) 307 | value2 := uint(data[0]) - 40*value1 308 | oid := Oid{value1, value2} 309 | 310 | reader := bytes.NewBuffer(data[1:]) 311 | for reader.Len() > 0 { 312 | valueN, err := decodeMultiByteTag(reader) 313 | if err != nil { 314 | return parseError("invalid value element in Object Identifier") 315 | } 316 | oid = append(oid, valueN) 317 | } 318 | 319 | value.Set(reflect.ValueOf(oid)) 320 | return nil 321 | } 322 | 323 | // Null is used to encode and decode ASN.1 NULLs. 324 | type Null struct{} 325 | 326 | func (ctx *Context) encodeNull(value reflect.Value) ([]byte, error) { 327 | _, ok := value.Interface().(Null) 328 | if !ok { 329 | return nil, wrongType(nullType.String(), value) 330 | } 331 | return []byte{}, nil 332 | } 333 | 334 | func (ctx *Context) decodeNull(data []byte, value reflect.Value) error { 335 | // TODO check value type 336 | _, ok := value.Interface().(Null) 337 | if !ok { 338 | return syntaxError("invalid type: %s", value.Type()) 339 | } 340 | if len(data) != 0 { 341 | return parseError("invalid data for Null type") 342 | } 343 | return nil 344 | } 345 | 346 | /* 347 | * Helper functions 348 | */ 349 | 350 | func checkInt(ctx *Context, data []byte) error { 351 | if ctx.der.decoding { 352 | if len(data) >= 2 { 353 | if data[0] == 0xff || data[0] == 0x00 { 354 | if data[0]&0x80 == data[1]&0x80 { 355 | return parseError("integer not encoded in the short form") 356 | } 357 | } 358 | } 359 | } 360 | return nil 361 | } 362 | 363 | func parseBigInt(data []byte) *big.Int { 364 | data = append([]byte{}, data...) 365 | neg := false 366 | if data[0]&0x80 != 0 { 367 | neg = true 368 | for i, b := range data { 369 | data[i] = ^b 370 | } 371 | } 372 | i := new(big.Int).SetBytes(data) 373 | if neg { 374 | i = i.Add(i, big.NewInt(1)).Neg(i) 375 | } 376 | return i 377 | } 378 | 379 | func removeIntLeadingBytes(buf []byte) []byte { 380 | start := 0 381 | for start < len(buf)-1 { 382 | // Removes a leading byte when the first NINE bits are the same 383 | 384 | // If the first 8 bits are not the same, skip 385 | if buf[start] != 0x00 && buf[start] != 0xff { 386 | break 387 | } 388 | 389 | // And if the 9th bit (1st bit of the second byte) is not the same as the previous 8 bits, also skip 390 | if (buf[start] & 0x80) != (buf[start+1] & 0x80) { 391 | break 392 | } 393 | 394 | // Remove a leading byte 395 | start++ 396 | } 397 | return buf[start:] 398 | } 399 | 400 | func wrongType(typeName string, value reflect.Value) error { 401 | return syntaxError( 402 | "invalid Go type '%s' found when expecting '%s'", 403 | value.Type(), typeName) 404 | } 405 | --------------------------------------------------------------------------------