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  */