// Package asn1tools provides tools for managing ASN1 marshaled data. package asn1tools import ( "github.com/jcmturner/gofork/encoding/asn1" ) // MarshalLengthBytes returns the ASN1 encoded bytes for the length 'l' // // There are two forms: short (for lengths between 0 and 127), and long definite (for lengths between 0 and 2^1008 -1). // // Short form: One octet. Bit 8 has value "0" and bits 7-1 give the length. // // 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. func MarshalLengthBytes(l int) []byte { if l <= 127 { return []byte{byte(l)} } var b []byte p := 1 for i := 1; i < 127; { b = append([]byte{byte((l % (p * 256)) / p)}, b...) p = p * 256 l = l - l%p if l <= 0 { break } } return append([]byte{byte(128 + len(b))}, b...) } // GetLengthFromASN returns the length of a slice of ASN1 encoded bytes from the ASN1 length header it contains. func GetLengthFromASN(b []byte) int { if int(b[1]) <= 127 { return int(b[1]) } // The bytes that indicate the length lb := b[2 : 2+int(b[1])-128] base := 1 l := 0 for i := len(lb) - 1; i >= 0; i-- { l += int(lb[i]) * base base = base * 256 } return l } // GetNumberBytesInLengthHeader returns the number of bytes in the ASn1 header that indicate the length. func GetNumberBytesInLengthHeader(b []byte) int { if int(b[1]) <= 127 { return 1 } // The bytes that indicate the length return 1 + int(b[1]) - 128 } // AddASNAppTag adds an ASN1 encoding application tag value to the raw bytes provided. func AddASNAppTag(b []byte, tag int) []byte { r := asn1.RawValue{ Class: asn1.ClassApplication, IsCompound: true, Tag: tag, Bytes: b, } ab, _ := asn1.Marshal(r) return ab } /* // The Marshal method of golang's asn1 package does not enable you to define wrapping the output in an application tag. // This method adds that wrapping tag. func AddASNAppTag(b []byte, tag int) []byte { // The ASN1 wrapping consists of 2 bytes: // 1st byte -> Identifier Octet - Application Tag // 2nd byte -> The length (this will be the size indicated in the input bytes + 2 for the additional bytes we add here. // Application Tag: //| Bit: | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | //| Value: | 0 | 1 | 1 | From the RFC spec 4120 | //| Explanation | Defined by the ASN1 encoding rules for an application tag | A value of 1 indicates a constructed type | The ASN Application tag value | // Therefore the value of the byte is an integer = ( Application tag value + 96 ) //b = append(MarshalLengthBytes(int(b[1])+2), b...) b = append(MarshalLengthBytes(len(b)), b...) b = append([]byte{byte(96 + tag)}, b...) return b } */