func couldBeT61(bytes []byte) bool {
	for _, b := range bytes {
		switch b {
		case 0x00:
			fallthrough
		case 0x23, 0x24, 0x5C, 0x5E, 0x60, 0x7B, 0x7D, 0x7E, 0xA5, 0xA6, 0xAC, 0xAD, 0xAE, 0xAF,
			0xB9, 0xBA, 0xC0, 0xC9, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
			0xDA, 0xDB, 0xDC, 0xDE, 0xDF, 0xE5, 0xFF:
			return false
		}
	}
	return true
}
Checks whether the data in |bytes| would be a valid T.61 string.
Clearly, a sequence of bytes comprised solely of valid T.61
codepoints does not imply that the encoding MUST be T.61, rather that
you would not encounter an error trying to interpret the data as such.
package asn1
import (
	"errors"
	"fmt"
	"math"
	"math/big"
	"reflect"
	"strconv"
	"time"
	"unicode/utf16"
	"unicode/utf8"
)
type StructuralError struct {
	Msg   string
	Field string
}
func (e StructuralError) Error() string {
	var prefix string
	if e.Field != "" {
		prefix = e.Field + ": "
	}
	return "asn1: structure error: " + prefix + e.Msg
}
type SyntaxError struct {
	Msg   string
	Field string
}
func (e SyntaxError) Error() string {
	var prefix string
	if e.Field != "" {
		prefix = e.Field + ": "
	}
	return "asn1: syntax error: " + prefix + e.Msg
}
func parseBool(bytes []byte, fieldName string) (ret bool, err error) {
	if len(bytes) != 1 {
		err = SyntaxError{"invalid boolean", fieldName}
		return
	}
	switch bytes[0] {
	case 0:
		ret = false
	case 0xff:
		ret = true
	default:
		err = SyntaxError{"invalid boolean", fieldName}
	}
	return
}
func checkInteger(bytes []byte, lax bool, fieldName string) error {
	if len(bytes) == 0 {
		return StructuralError{"empty integer", fieldName}
	}
	if len(bytes) == 1 {
		return nil
	}
	if lax {
		return nil
	}
	if (bytes[0] == 0 && bytes[1]&0x80 == 0) || (bytes[0] == 0xff && bytes[1]&0x80 == 0x80) {
		return StructuralError{"integer not minimally-encoded", fieldName}
	}
	return nil
}
func parseInt64(bytes []byte, lax bool, fieldName string) (ret int64, err error) {
	err = checkInteger(bytes, lax, fieldName)
	if err != nil {
		return
	}
	if len(bytes) > 8 {
		err = StructuralError{"integer too large", fieldName}
		return
	}
	for bytesRead := 0; bytesRead < len(bytes); bytesRead++ {
		ret <<= 8
		ret |= int64(bytes[bytesRead])
	}
	ret <<= 64 - uint8(len(bytes))*8
	ret >>= 64 - uint8(len(bytes))*8
	return
}
func parseInt32(bytes []byte, lax bool, fieldName string) (int32, error) {
	if err := checkInteger(bytes, lax, fieldName); err != nil {
		return 0, err
	}
	ret64, err := parseInt64(bytes, lax, fieldName)
	if err != nil {
		return 0, err
	}
	if ret64 != int64(int32(ret64)) {
		return 0, StructuralError{"integer too large", fieldName}
	}
	return int32(ret64), nil
}
var bigOne = big.NewInt(1)
func parseBigInt(bytes []byte, lax bool, fieldName string) (*big.Int, error) {
	if err := checkInteger(bytes, lax, fieldName); err != nil {
		return nil, err
	}
	ret := new(big.Int)
	if len(bytes) > 0 && bytes[0]&0x80 == 0x80 {
		notBytes := make([]byte, len(bytes))
		for i := range notBytes {
			notBytes[i] = ^bytes[i]
		}
		ret.SetBytes(notBytes)
		ret.Add(ret, bigOne)
		ret.Neg(ret)
		return ret, nil
	}
	ret.SetBytes(bytes)
	return ret, nil
}
type BitString struct {
	Bytes     []byte  
	BitLength int     
}
func (b BitString) At(i int) int {
	if i < 0 || i >= b.BitLength {
		return 0
	}
	x := i / 8
	y := 7 - uint(i%8)
	return int(b.Bytes[x]>>y) & 1
}
func (b BitString) RightAlign() []byte {
	shift := uint(8 - (b.BitLength % 8))
	if shift == 8 || len(b.Bytes) == 0 {
		return b.Bytes
	}
	a := make([]byte, len(b.Bytes))
	a[0] = b.Bytes[0] >> shift
	for i := 1; i < len(b.Bytes); i++ {
		a[i] = b.Bytes[i-1] << (8 - shift)
		a[i] |= b.Bytes[i] >> shift
	}
	return a
}
func parseBitString(bytes []byte, fieldName string) (ret BitString, err error) {
	if len(bytes) == 0 {
		err = SyntaxError{"zero length BIT STRING", fieldName}
		return
	}
	paddingBits := int(bytes[0])
	if paddingBits > 7 ||
		len(bytes) == 1 && paddingBits > 0 ||
		bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 {
		err = SyntaxError{"invalid padding bits in BIT STRING", fieldName}
		return
	}
	ret.BitLength = (len(bytes)-1)*8 - paddingBits
	ret.Bytes = bytes[1:]
	return
}
var NullRawValue = RawValue{Tag: TagNull}
var NullBytes = []byte{TagNull, 0}
type ObjectIdentifier []int
func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool {
	if len(oi) != len(other) {
		return false
	}
	for i := 0; i < len(oi); i++ {
		if oi[i] != other[i] {
			return false
		}
	}
	return true
}
func (oi ObjectIdentifier) String() string {
	var s string
	for i, v := range oi {
		if i > 0 {
			s += "."
		}
		s += strconv.Itoa(v)
	}
	return s
}
func parseObjectIdentifier(bytes []byte, lax bool, fieldName string) (s ObjectIdentifier, err error) {
	if len(bytes) == 0 {
		if lax {
			return ObjectIdentifier{}, nil
		}
		err = SyntaxError{"zero length OBJECT IDENTIFIER", fieldName}
		return
	}
	s = make([]int, len(bytes)+1)
	v, offset, err := parseBase128Int(bytes, 0, fieldName)
	if err != nil {
		return
	}
	if v < 80 {
		s[0] = v / 40
		s[1] = v % 40
	} else {
		s[0] = 2
		s[1] = v - 80
	}
	i := 2
	for ; offset < len(bytes); i++ {
		v, offset, err = parseBase128Int(bytes, offset, fieldName)
		if err != nil {
			return
		}
		s[i] = v
	}
	s = s[0:i]
	return
}
type Enumerated int
type Flag bool
func parseBase128Int(bytes []byte, initOffset int, fieldName string) (ret, offset int, err error) {
	offset = initOffset
	var ret64 int64
	for shifted := 0; offset < len(bytes); shifted++ {
		if shifted == 5 {
			err = StructuralError{"base 128 integer too large", fieldName}
			return
		}
		ret64 <<= 7
		b := bytes[offset]
		ret64 |= int64(b & 0x7f)
		offset++
		if b&0x80 == 0 {
			ret = int(ret64)
			if ret64 > math.MaxInt32 {
				err = StructuralError{"base 128 integer too large", fieldName}
			}
			return
		}
	}
	err = SyntaxError{"truncated base 128 integer", fieldName}
	return
}
func parseUTCTime(bytes []byte) (ret time.Time, err error) {
	s := string(bytes)
	formatStr := "0601021504Z0700"
	ret, err = time.Parse(formatStr, s)
	if err != nil {
		formatStr = "060102150405Z0700"
		ret, err = time.Parse(formatStr, s)
	}
	if err != nil {
		return
	}
	if serialized := ret.Format(formatStr); serialized != s {
		err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized)
		return
	}
	if ret.Year() >= 2050 {
		ret = ret.AddDate(-100, 0, 0)
	}
	return
}
func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) {
	const formatStr = "20060102150405Z0700"
	s := string(bytes)
	if ret, err = time.Parse(formatStr, s); err != nil {
		return
	}
	if serialized := ret.Format(formatStr); serialized != s {
		err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized)
	}
	return
}
func parseNumericString(bytes []byte, fieldName string) (ret string, err error) {
	for _, b := range bytes {
		if !isNumeric(b) {
			return "", SyntaxError{"NumericString contains invalid character", fieldName}
		}
	}
	return string(bytes), nil
}
func isNumeric(b byte) bool {
	return '0' <= b && b <= '9' ||
		b == ' '
}
func parsePrintableString(bytes []byte, lax bool, fieldName string) (ret string, err error) {
	for _, b := range bytes {
		if !isPrintable(b, allowAsterisk, allowAmpersand) {
			if !lax {
				err = SyntaxError{"PrintableString contains invalid character", fieldName}
			} else {
				switch {
				case couldBeISO8859_1(bytes):
					ret, err = iso8859_1ToUTF8(bytes), nil
				case couldBeT61(bytes):
					ret, err = parseT61String(bytes)
				default:
					err = SyntaxError{"PrintableString contains invalid character, couldn't determine correct String type", fieldName}
				}
			}
			return
		}
	}
	ret = string(bytes)
	return
}
type asteriskFlag bool
type ampersandFlag bool
const (
	allowAsterisk  asteriskFlag = true
	rejectAsterisk asteriskFlag = false
	allowAmpersand  ampersandFlag = true
	rejectAmpersand ampersandFlag = false
)
func isPrintable(b byte, asterisk asteriskFlag, ampersand ampersandFlag) bool {
	return 'a' <= b && b <= 'z' ||
		'A' <= b && b <= 'Z' ||
		'0' <= b && b <= '9' ||
		'\'' <= b && b <= ')' ||
		'+' <= b && b <= '/' ||
		b == ' ' ||
		b == ':' ||
		b == '=' ||
		b == '?' ||
		(bool(asterisk) && b == '*') ||
		(bool(ampersand) && b == '&')
}
func parseIA5String(bytes []byte, fieldName string) (ret string, err error) {
	for _, b := range bytes {
		if b >= utf8.RuneSelf {
			err = SyntaxError{"IA5String contains invalid character", fieldName}
			return
		}
	}
	ret = string(bytes)
	return
}
func parseT61String(bytes []byte) (ret string, err error) {
	return string(bytes), nil
}
func parseUTF8String(bytes []byte) (ret string, err error) {
	if !utf8.Valid(bytes) {
		return "", errors.New("asn1: invalid UTF-8 string")
	}
	return string(bytes), nil
}
func parseBMPString(bmpString []byte) (string, error) {
	if len(bmpString)%2 != 0 {
		return "", errors.New("pkcs12: odd-length BMP string")
	}
	if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 {
		bmpString = bmpString[:l-2]
	}
	s := make([]uint16, 0, len(bmpString)/2)
	for len(bmpString) > 0 {
		s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1]))
		bmpString = bmpString[2:]
	}
	return string(utf16.Decode(s)), nil
}
type RawValue struct {
	Class, Tag int
	IsCompound bool
	Bytes      []byte
	FullBytes  []byte  
}
type RawContent []byte
func parseTagAndLength(bytes []byte, initOffset int, fieldName string) (ret tagAndLength, offset int, err error) {
	offset = initOffset
	if offset >= len(bytes) {
		err = errors.New("asn1: internal error in parseTagAndLength")
		return
	}
	b := bytes[offset]
	offset++
	ret.class = int(b >> 6)
	ret.isCompound = b&0x20 == 0x20
	ret.tag = int(b & 0x1f)
	if ret.tag == 0x1f {
		ret.tag, offset, err = parseBase128Int(bytes, offset, fieldName)
		if err != nil {
			return
		}
		if ret.tag < 0x1f {
			err = SyntaxError{"non-minimal tag", fieldName}
			return
		}
	}
	if offset >= len(bytes) {
		err = SyntaxError{"truncated tag or length", fieldName}
		return
	}
	b = bytes[offset]
	offset++
	if b&0x80 == 0 {
		ret.length = int(b & 0x7f)
	} else {
		numBytes := int(b & 0x7f)
		if numBytes == 0 {
			err = SyntaxError{"indefinite length found (not DER)", fieldName}
			return
		}
		ret.length = 0
		for i := 0; i < numBytes; i++ {
			if offset >= len(bytes) {
				err = SyntaxError{"truncated tag or length", fieldName}
				return
			}
			b = bytes[offset]
			offset++
			if ret.length >= 1<<23 {
				err = StructuralError{"length too large", fieldName}
				return
			}
			ret.length <<= 8
			ret.length |= int(b)
			if ret.length == 0 {
				err = StructuralError{"superfluous leading zeros in length", fieldName}
				return
			}
		}
		if ret.length < 0x80 {
			err = StructuralError{"non-minimal length", fieldName}
			return
		}
	}
	return
}
func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type, lax bool, fieldName string) (ret reflect.Value, err error) {
	matchAny, expectedTag, compoundType, ok := getUniversalType(elemType)
	if !ok {
		err = StructuralError{"unknown Go type for slice", fieldName}
		return
	}
	numElements := 0
	for offset := 0; offset < len(bytes); {
		var t tagAndLength
		t, offset, err = parseTagAndLength(bytes, offset, fieldName)
		if err != nil {
			return
		}
		switch t.tag {
		case TagIA5String, TagGeneralString, TagT61String, TagUTF8String, TagNumericString, TagBMPString:
			t.tag = TagPrintableString
		case TagGeneralizedTime, TagUTCTime:
			t.tag = TagUTCTime
		}
		if !matchAny && (t.class != ClassUniversal || t.isCompound != compoundType || t.tag != expectedTag) {
			err = StructuralError{fmt.Sprintf("sequence tag mismatch (got:%+v, want:0/%d/%t)", t, expectedTag, compoundType), fieldName}
			return
		}
		if invalidLength(offset, t.length, len(bytes)) {
			err = SyntaxError{"truncated sequence", fieldName}
			return
		}
		offset += t.length
		numElements++
	}
	ret = reflect.MakeSlice(sliceType, numElements, numElements)
	params := fieldParameters{lax: lax}
	offset := 0
	for i := 0; i < numElements; i++ {
		offset, err = parseField(ret.Index(i), bytes, offset, params)
		if err != nil {
			return
		}
	}
	return
}
var (
	bitStringType        = reflect.TypeOf(BitString{})
	objectIdentifierType = reflect.TypeOf(ObjectIdentifier{})
	enumeratedType       = reflect.TypeOf(Enumerated(0))
	flagType             = reflect.TypeOf(Flag(false))
	timeType             = reflect.TypeOf(time.Time{})
	rawValueType         = reflect.TypeOf(RawValue{})
	rawContentsType      = reflect.TypeOf(RawContent(nil))
	bigIntType           = reflect.TypeOf(new(big.Int))
)
func invalidLength(offset, length, sliceLength int) bool {
	return offset+length < offset || offset+length > sliceLength
}
func couldBeISO8859_1(bytes []byte) bool {
	for _, b := range bytes {
		if b < 0x20 || (b >= 0x7F && b < 0xA0) {
			return false
		}
	}
	return true
}