Source File
asn1.go
Belonging Package
encoding/asn1
package asn1
import (
)
type StructuralError struct {
Msg string
}
func ( StructuralError) () string { return "asn1: structure error: " + .Msg }
type SyntaxError struct {
Msg string
}
func ( SyntaxError) () string { return "asn1: syntax error: " + .Msg }
func ( []byte) ( bool, error) {
if len() != 1 {
= SyntaxError{"invalid boolean"}
return
}
switch [0] {
case 0:
= false
case 0xff:
= true
default:
= SyntaxError{"invalid boolean"}
}
return
}
func ( []byte) error {
if len() == 0 {
return StructuralError{"empty integer"}
}
if len() == 1 {
return nil
}
if ([0] == 0 && [1]&0x80 == 0) || ([0] == 0xff && [1]&0x80 == 0x80) {
return StructuralError{"integer not minimally-encoded"}
}
return nil
}
func ( []byte) ( int64, error) {
= checkInteger()
if != nil {
return
}
= StructuralError{"integer too large"}
return
}
for := 0; < len(); ++ {
<<= 8
|= int64([])
}
func ( []byte) (int32, error) {
if := checkInteger(); != nil {
return 0,
}
, := parseInt64()
if != nil {
return 0,
}
if != int64(int32()) {
return 0, StructuralError{"integer too large"}
}
return int32(), nil
}
var bigOne = big.NewInt(1)
var NullRawValue = RawValue{Tag: TagNull}
type ObjectIdentifier []int
func ( ObjectIdentifier) ( ObjectIdentifier) bool {
if len() != len() {
return false
}
for := 0; < len(); ++ {
if [] != [] {
return false
}
}
return true
}
func ( ObjectIdentifier) () string {
var string
for , := range {
if > 0 {
+= "."
}
+= strconv.Itoa()
}
return
}
func ( []byte) ( ObjectIdentifier, error) {
if len() == 0 {
= SyntaxError{"zero length OBJECT IDENTIFIER"}
return
}
, , := parseBase128Int(, 0)
if != nil {
return
}
if < 80 {
[0] = / 40
[1] = % 40
} else {
[0] = 2
[1] = - 80
}
:= 2
for ; < len(); ++ {
, , = parseBase128Int(, )
if != nil {
return
}
[] =
}
= [0:]
return
}
type Enumerated int
if == 5 {
= StructuralError{"base 128 integer too large"}
return
}
<<= 7
if == 0 && == 0x80 {
= SyntaxError{"integer is not minimally encoded"}
return
}
|= int64( & 0x7f)
++
if &0x80 == 0 {
if > math.MaxInt32 {
= StructuralError{"base 128 integer too large"}
}
return
}
}
= SyntaxError{"truncated base 128 integer"}
return
}
func ( []byte) ( time.Time, error) {
:= string()
:= "0601021504Z0700"
, = time.Parse(, )
if != nil {
= "060102150405Z0700"
, = time.Parse(, )
}
if != nil {
return
}
if := .Format(); != {
= fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", , )
return
}
= .AddDate(-100, 0, 0)
}
return
}
func ( []byte) ( string, error) {
for , := range {
if !isPrintable(, allowAsterisk, allowAmpersand) {
= SyntaxError{"PrintableString contains invalid character"}
return
}
}
= string()
return
}
type asteriskFlag bool
type ampersandFlag bool
const (
allowAsterisk asteriskFlag = true
rejectAsterisk asteriskFlag = false
allowAmpersand ampersandFlag = true
rejectAmpersand ampersandFlag = false
)
func ( byte, asteriskFlag, ampersandFlag) bool {
return 'a' <= && <= 'z' ||
'A' <= && <= 'Z' ||
'0' <= && <= '9' ||
'\'' <= && <= ')' ||
'+' <= && <= '/' ||
== ' ' ||
== ':' ||
== '=' ||
(bool() && == '&')
}
type RawContent []byte
func ( []byte, int) ( tagAndLength, int, error) {
if .tag == 0x1f {
.tag, , = parseBase128Int(, )
if != nil {
return
if .tag < 0x1f {
= SyntaxError{"non-minimal tag"}
return
}
}
if >= len() {
= SyntaxError{"truncated tag or length"}
return
}
= []
++
:= int( & 0x7f)
if == 0 {
= SyntaxError{"indefinite length found (not DER)"}
return
}
.length = 0
for := 0; < ; ++ {
if >= len() {
= SyntaxError{"truncated tag or length"}
return
}
= []
++
= StructuralError{"length too large"}
return
}
.length <<= 8
.length |= int()
= StructuralError{"superfluous leading zeros in length"}
return
}
if .length < 0x80 {
= StructuralError{"non-minimal length"}
return
}
}
return
}
func ( []byte, reflect.Type, reflect.Type) ( reflect.Value, error) {
, , , := getUniversalType()
if ! {
= StructuralError{"unknown Go type for slice"}
return
}
:= 0
for := 0; < len(); {
var tagAndLength
, , = parseTagAndLength(, )
if != nil {
return
}
switch .tag {
.tag = TagUTCTime
}
if ! && (.class != ClassUniversal || .isCompound != || .tag != ) {
= StructuralError{"sequence tag mismatch"}
return
}
if invalidLength(, .length, len()) {
= SyntaxError{"truncated sequence"}
return
}
+= .length
++
}
= reflect.MakeSlice(, , )
:= fieldParameters{}
:= 0
for := 0; < ; ++ {
, = parseField(.Index(), , , )
if != 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))
)
if == len() {
if !setDefaultValue(, ) {
= SyntaxError{"sequence truncated"}
}
return
}
if := ; .Kind() == reflect.Interface && .NumMethod() == 0 {
var tagAndLength
, , = parseTagAndLength(, )
if != nil {
return
}
if invalidLength(, .length, len()) {
= SyntaxError{"data truncated"}
return
}
var interface{}
if !.isCompound && .class == ClassUniversal {
:= [ : +.length]
switch .tag {
case TagPrintableString:
, = parsePrintableString()
case TagNumericString:
, = parseNumericString()
case TagIA5String:
, = parseIA5String()
case TagT61String:
, = parseT61String()
case TagUTF8String:
, = parseUTF8String()
case TagInteger:
, = parseInt64()
case TagBitString:
, = parseBitString()
case TagOID:
, = parseObjectIdentifier()
case TagUTCTime:
, = parseUTCTime()
case TagGeneralizedTime:
, = parseGeneralizedTime()
case TagOctetString:
=
case TagBMPString:
, = parseBMPString()
}
}
+= .length
if != nil {
return
}
if != nil {
.Set(reflect.ValueOf())
}
return
}
, , := parseTagAndLength(, )
if != nil {
return
}
if .explicit {
:= ClassContextSpecific
if .application {
= ClassApplication
}
if == len() {
= StructuralError{"explicit tag has no child"}
return
}
if .class == && .tag == *.tag && (.length == 0 || .isCompound) {
} else if .length > 0 {
, , = parseTagAndLength(, )
if != nil {
return
}
} else {
if != flagType {
= StructuralError{"zero length explicit tag was not an asn1.Flag"}
return
}
.SetBool(true)
return
}
:= setDefaultValue(, )
if {
=
} else {
= StructuralError{"explicitly tagged member didn't match"}
}
return
}
}
, , , := getUniversalType()
if ! {
= StructuralError{fmt.Sprintf("unknown Go type: %v", )}
return
}
if == TagPrintableString {
if .class == ClassUniversal {
switch .tag {
case TagIA5String, TagGeneralString, TagT61String, TagUTF8String, TagNumericString, TagBMPString:
= .tag
}
} else if .stringType != 0 {
= .stringType
}
}
if == TagUTCTime && .tag == TagGeneralizedTime && .class == ClassUniversal {
= TagGeneralizedTime
}
if .set {
= TagSet
}
:=
:= ClassUniversal
:=
if !.explicit && .tag != nil {
= ClassContextSpecific
= *.tag
= false
}
if !.explicit && .application && .tag != nil {
= ClassApplication
= *.tag
= false
}
if !.explicit && .private && .tag != nil {
= ClassPrivate
= *.tag
= false
}
:= setDefaultValue(, )
if {
=
} else {
= StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", , , , .Name(), )}
}
return
}
if invalidLength(, .length, len()) {
= SyntaxError{"data truncated"}
return
}
:= [ : +.length]
+= .length
switch v := .Addr().Interface().(type) {
case *RawValue:
* = RawValue{.class, .tag, .isCompound, , [:]}
return
case *ObjectIdentifier:
*, = parseObjectIdentifier()
return
case *BitString:
*, = parseBitString()
return
case *time.Time:
if == TagUTCTime {
*, = parseUTCTime()
return
}
*, = parseGeneralizedTime()
return
case *Enumerated:
, := parseInt32()
if == nil {
* = Enumerated()
}
=
return
case *Flag:
* = true
return
case **big.Int:
, := parseBigInt()
if == nil {
* =
}
=
return
}
switch := ; .Kind() {
case reflect.Bool:
, := parseBool()
if == nil {
.SetBool()
}
=
return
case reflect.Int, reflect.Int32, reflect.Int64:
if .Type().Size() == 4 {
, := parseInt32()
if == nil {
.SetInt(int64())
}
=
} else {
, := parseInt64()
if == nil {
.SetInt()
}
=
}
case reflect.Struct:
:=
for := 0; < .NumField(); ++ {
if .Field().PkgPath != "" {
= StructuralError{"struct contains unexported fields"}
return
}
}
if .NumField() > 0 &&
.Field(0).Type == rawContentsType {
:= [:]
.Field(0).Set(reflect.ValueOf(RawContent()))
}
:= 0
for := 0; < .NumField(); ++ {
:= .Field()
if == 0 && .Type == rawContentsType {
continue
}
, = (.Field(), , , parseFieldParameters(.Tag.Get("asn1")))
if != nil {
return
}
return
case reflect.Slice:
:=
if .Elem().Kind() == reflect.Uint8 {
.Set(reflect.MakeSlice(, len(), len()))
reflect.Copy(, reflect.ValueOf())
return
}
, := parseSequenceOf(, , .Elem())
if == nil {
.Set()
}
=
return
case reflect.String:
var string
switch {
case TagPrintableString:
, = parsePrintableString()
case TagNumericString:
, = parseNumericString()
case TagIA5String:
, = parseIA5String()
case TagT61String:
, = parseT61String()
case TagUTF8String:
, = parseUTF8String()
, = parseT61String()
case TagBMPString:
, = parseBMPString()
default:
= SyntaxError{fmt.Sprintf("internal error: unknown string type %d", )}
}
if == nil {
.SetString()
}
return
}
= StructuralError{"unsupported: " + .Type().String()}
return
}
func ( reflect.Value, fieldParameters) ( bool) {
if !.optional {
return
}
= true
if .defaultValue == nil {
return
}
if canHaveDefaultValue(.Kind()) {
.SetInt(*.defaultValue)
}
return
}
func ( []byte, interface{}) ( []byte, error) {
return UnmarshalWithParams(, , "")
}
type invalidUnmarshalError struct {
Type reflect.Type
}
func ( *invalidUnmarshalError) () string {
if .Type == nil {
return "asn1: Unmarshal recipient value is nil"
}
if .Type.Kind() != reflect.Ptr {
return "asn1: Unmarshal recipient value is non-pointer " + .Type.String()
}
return "asn1: Unmarshal recipient value is nil " + .Type.String()
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |