87 lines
2.9 KiB
Go
87 lines
2.9 KiB
Go
// 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
|
|
}
|
|
*/
|