package datastructures import ( "bytes" "encoding/binary" "errors" "fmt" "time" ) type SignerRequest struct { Version uint8 Action Action System uint8 Root uint8 Configuration uint8 Parameter1 uint8 Parameter2 uint16 Parameter3 uint8 Content1 string Content2 string Content3 string } const protocolVersion = 1 func SignerRequestFromData(lengthBytes []byte, blockData []byte, checkSum byte) (*SignerRequest, error) { headerLength := decode24BitLength(blockData[0:3]) headerBytes := blockData[3 : 3+headerLength] contentBytes := blockData[3+headerLength:] content1Length := decode24BitLength(contentBytes[0:3]) content1 := string(contentBytes[3 : 3+content1Length]) content2Offset := 3 + content1Length content2Length := decode24BitLength(contentBytes[content2Offset : content2Offset+3]) content2 := string(contentBytes[3+content2Offset : 3+content2Offset+content2Length]) content3Offset := 3 + content2Offset + content2Length content3Length := decode24BitLength(contentBytes[content3Offset : content3Offset+3]) content3 := string(contentBytes[3+content3Offset : 3+content3Offset+content3Length]) calculated := CalculateXorCheckSum([][]byte{lengthBytes, blockData}) if checkSum != calculated { return nil, errors.New(fmt.Sprintf("invalid checksum expected 0x%x got 0x%x", calculated, checkSum)) } return &SignerRequest{ Version: headerBytes[0], Action: Action(headerBytes[1]), System: headerBytes[2], Root: headerBytes[3], Configuration: headerBytes[4], Parameter1: headerBytes[5], Parameter2: binary.BigEndian.Uint16([]byte{headerBytes[6], headerBytes[7]}), Parameter3: headerBytes[8], Content1: content1, Content2: content2, Content3: content3, }, nil } func (r SignerRequest) Serialize() []byte { parameter2Bytes := make([]byte, 2) binary.BigEndian.PutUint16(parameter2Bytes, r.Parameter2) headerBytes := bytes.Join([][]byte{ {r.Version, byte(r.Action), r.System, r.Root, r.Configuration, r.Parameter1}, parameter2Bytes, {r.Parameter3}}, []byte{}) content1Bytes := []byte(r.Content1) content2Bytes := []byte(r.Content2) content3Bytes := []byte(r.Content3) blockBytes := bytes.Join([][]byte{ encode24BitLength(headerBytes), headerBytes, encode24BitLength(content1Bytes), content1Bytes, encode24BitLength(content2Bytes), content2Bytes, encode24BitLength(content3Bytes), content3Bytes, }, []byte{}) return bytes.Join([][]byte{encode24BitLength(blockBytes), blockBytes}, []byte{}) } func NewNulRequest() *SignerRequest { return &SignerRequest{ Version: protocolVersion, Action: ActionNul, Content1: time.Now().UTC().Format("010203042006.05"), } }