1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
17 byte00Encoder encoder
= byteEncoder(0x00)
18 byteFFEncoder encoder
= byteEncoder(0xff)
21 // encoder represents a ASN.1 element that is waiting to be marshaled.
22 type encoder
interface {
23 // Len returns the number of bytes needed to marshal this element.
25 // Encode encodes this element by writing Len() bytes to dst.
31 func (c byteEncoder
) Len() int {
35 func (c byteEncoder
) Encode(dst
[]byte) {
39 type bytesEncoder
[]byte
41 func (b bytesEncoder
) Len() int {
45 func (b bytesEncoder
) Encode(dst
[]byte) {
46 if copy(dst
, b
) != len(b
) {
47 panic("internal error")
51 type stringEncoder
string
53 func (s stringEncoder
) Len() int {
57 func (s stringEncoder
) Encode(dst
[]byte) {
58 if copy(dst
, s
) != len(s
) {
59 panic("internal error")
63 type multiEncoder
[]encoder
65 func (m multiEncoder
) Len() int {
73 func (m multiEncoder
) Encode(dst
[]byte) {
81 type taggedEncoder
struct {
82 // scratch contains temporary space for encoding the tag and length of
83 // an element in order to avoid extra allocations.
89 func (t
*taggedEncoder
) Len() int {
90 return t
.tag
.Len() + t
.body
.Len()
93 func (t
*taggedEncoder
) Encode(dst
[]byte) {
95 t
.body
.Encode(dst
[t
.tag
.Len():])
98 type int64Encoder
int64
100 func (i int64Encoder
) Len() int {
116 func (i int64Encoder
) Encode(dst
[]byte) {
119 for j
:= 0; j
< n
; j
++ {
120 dst
[j
] = byte(i
>> uint((n
-1-j
)*8))
124 func base128IntLength(n
int64) int {
130 for i
:= n
; i
> 0; i
>>= 7 {
137 func appendBase128Int(dst
[]byte, n
int64) []byte {
138 l
:= base128IntLength(n
)
140 for i
:= l
- 1; i
>= 0; i
-- {
141 o
:= byte(n
>> uint(i
*7))
153 func makeBigInt(n
*big
.Int
) (encoder
, error
) {
155 return nil, StructuralError
{"empty integer"}
159 // A negative number has to be converted to two's-complement
160 // form. So we'll invert and subtract 1. If the
161 // most-significant-bit isn't set then we'll need to pad the
162 // beginning with 0xff in order to keep the number negative.
163 nMinus1
:= new(big
.Int
).Neg(n
)
164 nMinus1
.Sub(nMinus1
, bigOne
)
165 bytes
:= nMinus1
.Bytes()
166 for i
:= range bytes
{
169 if len(bytes
) == 0 || bytes
[0]&0x80 == 0 {
170 return multiEncoder([]encoder
{byteFFEncoder
, bytesEncoder(bytes
)}), nil
172 return bytesEncoder(bytes
), nil
173 } else if n
.Sign() == 0 {
174 // Zero is written as a single 0 zero rather than no bytes.
175 return byte00Encoder
, nil
178 if len(bytes
) > 0 && bytes
[0]&0x80 != 0 {
179 // We'll have to pad this with 0x00 in order to stop it
180 // looking like a negative number.
181 return multiEncoder([]encoder
{byte00Encoder
, bytesEncoder(bytes
)}), nil
183 return bytesEncoder(bytes
), nil
187 func appendLength(dst
[]byte, i
int) []byte {
191 dst
= append(dst
, byte(i
>>uint((n
-1)*8)))
197 func lengthLength(i
int) (numBytes
int) {
206 func appendTagAndLength(dst
[]byte, t tagAndLength
) []byte {
207 b
:= uint8(t
.class
) << 6
214 dst
= appendBase128Int(dst
, int64(t
.tag
))
221 l
:= lengthLength(t
.length
)
222 dst
= append(dst
, 0x80|
byte(l
))
223 dst
= appendLength(dst
, t
.length
)
225 dst
= append(dst
, byte(t
.length
))
231 type bitStringEncoder BitString
233 func (b bitStringEncoder
) Len() int {
234 return len(b
.Bytes
) + 1
237 func (b bitStringEncoder
) Encode(dst
[]byte) {
238 dst
[0] = byte((8 - b
.BitLength%8
) % 8)
239 if copy(dst
[1:], b
.Bytes
) != len(b
.Bytes
) {
240 panic("internal error")
244 type oidEncoder
[]int
246 func (oid oidEncoder
) Len() int {
247 l
:= base128IntLength(int64(oid
[0]*40 + oid
[1]))
248 for i
:= 2; i
< len(oid
); i
++ {
249 l
+= base128IntLength(int64(oid
[i
]))
254 func (oid oidEncoder
) Encode(dst
[]byte) {
255 dst
= appendBase128Int(dst
[:0], int64(oid
[0]*40+oid
[1]))
256 for i
:= 2; i
< len(oid
); i
++ {
257 dst
= appendBase128Int(dst
, int64(oid
[i
]))
261 func makeObjectIdentifier(oid
[]int) (e encoder
, err error
) {
262 if len(oid
) < 2 || oid
[0] > 2 ||
(oid
[0] < 2 && oid
[1] >= 40) {
263 return nil, StructuralError
{"invalid object identifier"}
266 return oidEncoder(oid
), nil
269 func makePrintableString(s
string) (e encoder
, err error
) {
270 for i
:= 0; i
< len(s
); i
++ {
271 if !isPrintable(s
[i
]) {
272 return nil, StructuralError
{"PrintableString contains invalid character"}
276 return stringEncoder(s
), nil
279 func makeIA5String(s
string) (e encoder
, err error
) {
280 for i
:= 0; i
< len(s
); i
++ {
282 return nil, StructuralError
{"IA5String contains invalid character"}
286 return stringEncoder(s
), nil
289 func makeUTF8String(s
string) encoder
{
290 return stringEncoder(s
)
293 func appendTwoDigits(dst
[]byte, v
int) []byte {
294 return append(dst
, byte('0'+(v
/10)%10
), byte('0'+v%10
))
297 func appendFourDigits(dst
[]byte, v
int) []byte {
299 for i
:= range bytes
{
300 bytes
[3-i
] = '0' + byte(v%10
)
303 return append(dst
, bytes
[:]...)
306 func outsideUTCRange(t time
.Time
) bool {
308 return year
< 1950 || year
>= 2050
311 func makeUTCTime(t time
.Time
) (e encoder
, err error
) {
312 dst
:= make([]byte, 0, 18)
314 dst
, err
= appendUTCTime(dst
, t
)
319 return bytesEncoder(dst
), nil
322 func makeGeneralizedTime(t time
.Time
) (e encoder
, err error
) {
323 dst
:= make([]byte, 0, 20)
325 dst
, err
= appendGeneralizedTime(dst
, t
)
330 return bytesEncoder(dst
), nil
333 func appendUTCTime(dst
[]byte, t time
.Time
) (ret
[]byte, err error
) {
337 case 1950 <= year
&& year
< 2000:
338 dst
= appendTwoDigits(dst
, year
-1900)
339 case 2000 <= year
&& year
< 2050:
340 dst
= appendTwoDigits(dst
, year
-2000)
342 return nil, StructuralError
{"cannot represent time as UTCTime"}
345 return appendTimeCommon(dst
, t
), nil
348 func appendGeneralizedTime(dst
[]byte, t time
.Time
) (ret
[]byte, err error
) {
350 if year
< 0 || year
> 9999 {
351 return nil, StructuralError
{"cannot represent time as GeneralizedTime"}
354 dst
= appendFourDigits(dst
, year
)
356 return appendTimeCommon(dst
, t
), nil
359 func appendTimeCommon(dst
[]byte, t time
.Time
) []byte {
360 _
, month
, day
:= t
.Date()
362 dst
= appendTwoDigits(dst
, int(month
))
363 dst
= appendTwoDigits(dst
, day
)
365 hour
, min
, sec
:= t
.Clock()
367 dst
= appendTwoDigits(dst
, hour
)
368 dst
= appendTwoDigits(dst
, min
)
369 dst
= appendTwoDigits(dst
, sec
)
371 _
, offset
:= t
.Zone()
375 return append(dst
, 'Z')
377 dst
= append(dst
, '+')
379 dst
= append(dst
, '-')
382 offsetMinutes
:= offset
/ 60
383 if offsetMinutes
< 0 {
384 offsetMinutes
= -offsetMinutes
387 dst
= appendTwoDigits(dst
, offsetMinutes
/60)
388 dst
= appendTwoDigits(dst
, offsetMinutes%60
)
393 func stripTagAndLength(in
[]byte) []byte {
394 _
, offset
, err
:= parseTagAndLength(in
, 0)
401 func makeBody(value reflect
.Value
, params fieldParameters
) (e encoder
, err error
) {
402 switch value
.Type() {
404 return bytesEncoder(nil), nil
406 t
:= value
.Interface().(time
.Time
)
407 if params
.timeType
== TagGeneralizedTime ||
outsideUTCRange(t
) {
408 return makeGeneralizedTime(t
)
410 return makeUTCTime(t
)
412 return bitStringEncoder(value
.Interface().(BitString
)), nil
413 case objectIdentifierType
:
414 return makeObjectIdentifier(value
.Interface().(ObjectIdentifier
))
416 return makeBigInt(value
.Interface().(*big
.Int
))
419 switch v
:= value
; v
.Kind() {
422 return byteFFEncoder
, nil
424 return byte00Encoder
, nil
425 case reflect
.Int
, reflect
.Int8
, reflect
.Int16
, reflect
.Int32
, reflect
.Int64
:
426 return int64Encoder(v
.Int()), nil
430 for i
:= 0; i
< t
.NumField(); i
++ {
431 if t
.Field(i
).PkgPath
!= "" {
432 return nil, StructuralError
{"struct contains unexported fields"}
440 return bytesEncoder(nil), nil
443 // If the first element of the structure is a non-empty
444 // RawContents, then we don't bother serializing the rest.
445 if t
.Field(0).Type
== rawContentsType
{
449 /* The RawContents will contain the tag and
450 * length fields but we'll also be writing
451 * those ourselves, so we strip them out of
453 return bytesEncoder(stripTagAndLength(bytes
)), nil
459 switch n1
:= n
- startingField
; n1
{
461 return bytesEncoder(nil), nil
463 return makeField(v
.Field(startingField
), parseFieldParameters(t
.Field(startingField
).Tag
.Get("asn1")))
465 m
:= make([]encoder
, n1
)
466 for i
:= 0; i
< n1
; i
++ {
467 m
[i
], err
= makeField(v
.Field(i
+startingField
), parseFieldParameters(t
.Field(i
+startingField
).Tag
.Get("asn1")))
473 return multiEncoder(m
), nil
476 sliceType
:= v
.Type()
477 if sliceType
.Elem().Kind() == reflect
.Uint8
{
478 return bytesEncoder(v
.Bytes()), nil
481 var fp fieldParameters
483 switch l
:= v
.Len(); l
{
485 return bytesEncoder(nil), nil
487 return makeField(v
.Index(0), fp
)
489 m
:= make([]encoder
, l
)
491 for i
:= 0; i
< l
; i
++ {
492 m
[i
], err
= makeField(v
.Index(i
), fp
)
498 return multiEncoder(m
), nil
501 switch params
.stringType
{
503 return makeIA5String(v
.String())
504 case TagPrintableString
:
505 return makePrintableString(v
.String())
507 return makeUTF8String(v
.String()), nil
511 return nil, StructuralError
{"unknown Go type"}
514 func makeField(v reflect
.Value
, params fieldParameters
) (e encoder
, err error
) {
516 return nil, fmt
.Errorf("asn1: cannot marshal nil value")
518 // If the field is an interface{} then recurse into it.
519 if v
.Kind() == reflect
.Interface
&& v
.Type().NumMethod() == 0 {
520 return makeField(v
.Elem(), params
)
523 if v
.Kind() == reflect
.Slice
&& v
.Len() == 0 && params
.omitEmpty
{
524 return bytesEncoder(nil), nil
527 if params
.optional
&& params
.defaultValue
!= nil && canHaveDefaultValue(v
.Kind()) {
528 defaultValue
:= reflect
.New(v
.Type()).Elem()
529 defaultValue
.SetInt(*params
.defaultValue
)
531 if reflect
.DeepEqual(v
.Interface(), defaultValue
.Interface()) {
532 return bytesEncoder(nil), nil
536 // If no default value is given then the zero value for the type is
537 // assumed to be the default value. This isn't obviously the correct
538 // behavior, but it's what Go has traditionally done.
539 if params
.optional
&& params
.defaultValue
== nil {
540 if reflect
.DeepEqual(v
.Interface(), reflect
.Zero(v
.Type()).Interface()) {
541 return bytesEncoder(nil), nil
545 if v
.Type() == rawValueType
{
546 rv
:= v
.Interface().(RawValue
)
547 if len(rv
.FullBytes
) != 0 {
548 return bytesEncoder(rv
.FullBytes
), nil
551 t
:= new(taggedEncoder
)
553 t
.tag
= bytesEncoder(appendTagAndLength(t
.scratch
[:0], tagAndLength
{rv
.Class
, rv
.Tag
, len(rv
.Bytes
), rv
.IsCompound
}))
554 t
.body
= bytesEncoder(rv
.Bytes
)
559 tag
, isCompound
, ok
:= getUniversalType(v
.Type())
561 return nil, StructuralError
{fmt
.Sprintf("unknown Go type: %v", v
.Type())}
563 class
:= ClassUniversal
565 if params
.timeType
!= 0 && tag
!= TagUTCTime
{
566 return nil, StructuralError
{"explicit time type given to non-time member"}
569 if params
.stringType
!= 0 && tag
!= TagPrintableString
{
570 return nil, StructuralError
{"explicit string type given to non-string member"}
574 case TagPrintableString
:
575 if params
.stringType
== 0 {
576 // This is a string without an explicit string type. We'll use
577 // a PrintableString if the character set in the string is
578 // sufficiently limited, otherwise we'll use a UTF8String.
579 for _
, r
:= range v
.String() {
580 if r
>= utf8
.RuneSelf ||
!isPrintable(byte(r
)) {
581 if !utf8
.ValidString(v
.String()) {
582 return nil, errors
.New("asn1: string not valid UTF-8")
589 tag
= params
.stringType
592 if params
.timeType
== TagGeneralizedTime ||
outsideUTCRange(v
.Interface().(time
.Time
)) {
593 tag
= TagGeneralizedTime
598 if tag
!= TagSequence
{
599 return nil, StructuralError
{"non sequence tagged as set"}
604 t
:= new(taggedEncoder
)
606 t
.body
, err
= makeBody(v
, params
)
611 bodyLen
:= t
.body
.Len()
614 t
.tag
= bytesEncoder(appendTagAndLength(t
.scratch
[:0], tagAndLength
{class
, tag
, bodyLen
, isCompound
}))
616 tt
:= new(taggedEncoder
)
620 tt
.tag
= bytesEncoder(appendTagAndLength(tt
.scratch
[:0], tagAndLength
{
621 class
: ClassContextSpecific
,
623 length
: bodyLen
+ t
.tag
.Len(),
630 if params
.tag
!= nil {
633 class
= ClassContextSpecific
636 t
.tag
= bytesEncoder(appendTagAndLength(t
.scratch
[:0], tagAndLength
{class
, tag
, bodyLen
, isCompound
}))
641 // Marshal returns the ASN.1 encoding of val.
643 // In addition to the struct tags recognised by Unmarshal, the following can be
646 // ia5: causes strings to be marshaled as ASN.1, IA5String values
647 // omitempty: causes empty slices to be skipped
648 // printable: causes strings to be marshaled as ASN.1, PrintableString values
649 // utf8: causes strings to be marshaled as ASN.1, UTF8String values
650 // utc: causes time.Time to be marshaled as ASN.1, UTCTime values
651 // generalized: causes time.Time to be marshaled as ASN.1, GeneralizedTime values
652 func Marshal(val
interface{}) ([]byte, error
) {
653 e
, err
:= makeField(reflect
.ValueOf(val
), fieldParameters
{})
657 b
:= make([]byte, e
.Len())