github.com/jcmturner/gokrb5/v8@v8.4.4/asn1tools/tools.go (about) 1 // Package asn1tools provides tools for managing ASN1 marshaled data. 2 package asn1tools 3 4 import ( 5 "github.com/jcmturner/gofork/encoding/asn1" 6 ) 7 8 // MarshalLengthBytes returns the ASN1 encoded bytes for the length 'l' 9 // 10 // There are two forms: short (for lengths between 0 and 127), and long definite (for lengths between 0 and 2^1008 -1). 11 // 12 // Short form: One octet. Bit 8 has value "0" and bits 7-1 give the length. 13 // 14 // Long form: Two to 127 octets. Bit 8 of first octet has value "1" and bits 7-1 give the number of additional length octets. Second and following octets give the length, base 256, most significant digit first. 15 func MarshalLengthBytes(l int) []byte { 16 if l <= 127 { 17 return []byte{byte(l)} 18 } 19 var b []byte 20 p := 1 21 for i := 1; i < 127; { 22 b = append([]byte{byte((l % (p * 256)) / p)}, b...) 23 p = p * 256 24 l = l - l%p 25 if l <= 0 { 26 break 27 } 28 } 29 return append([]byte{byte(128 + len(b))}, b...) 30 } 31 32 // GetLengthFromASN returns the length of a slice of ASN1 encoded bytes from the ASN1 length header it contains. 33 func GetLengthFromASN(b []byte) int { 34 if int(b[1]) <= 127 { 35 return int(b[1]) 36 } 37 // The bytes that indicate the length 38 lb := b[2 : 2+int(b[1])-128] 39 base := 1 40 l := 0 41 for i := len(lb) - 1; i >= 0; i-- { 42 l += int(lb[i]) * base 43 base = base * 256 44 } 45 return l 46 } 47 48 // GetNumberBytesInLengthHeader returns the number of bytes in the ASn1 header that indicate the length. 49 func GetNumberBytesInLengthHeader(b []byte) int { 50 if int(b[1]) <= 127 { 51 return 1 52 } 53 // The bytes that indicate the length 54 return 1 + int(b[1]) - 128 55 } 56 57 // AddASNAppTag adds an ASN1 encoding application tag value to the raw bytes provided. 58 func AddASNAppTag(b []byte, tag int) []byte { 59 r := asn1.RawValue{ 60 Class: asn1.ClassApplication, 61 IsCompound: true, 62 Tag: tag, 63 Bytes: b, 64 } 65 ab, _ := asn1.Marshal(r) 66 return ab 67 } 68 69 /* 70 // The Marshal method of golang's asn1 package does not enable you to define wrapping the output in an application tag. 71 // This method adds that wrapping tag. 72 func AddASNAppTag(b []byte, tag int) []byte { 73 // The ASN1 wrapping consists of 2 bytes: 74 // 1st byte -> Identifier Octet - Application Tag 75 // 2nd byte -> The length (this will be the size indicated in the input bytes + 2 for the additional bytes we add here. 76 // Application Tag: 77 //| Bit: | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 78 //| Value: | 0 | 1 | 1 | From the RFC spec 4120 | 79 //| Explanation | Defined by the ASN1 encoding rules for an application tag | A value of 1 indicates a constructed type | The ASN Application tag value | 80 // Therefore the value of the byte is an integer = ( Application tag value + 96 ) 81 //b = append(MarshalLengthBytes(int(b[1])+2), b...) 82 b = append(MarshalLengthBytes(len(b)), b...) 83 b = append([]byte{byte(96 + tag)}, b...) 84 return b 85 } 86 */