package datastructures import ( "bytes" "errors" "fmt" "git.cacert.org/cacert-gosigner/shared" ) type SignerResponse struct { Version uint8 Action shared.Action Reserved1 uint8 Reserved2 uint8 Content []byte Argument1 []byte Argument2 []byte } func SignerResponseFromData(lengthBytes []byte, blockData []byte, checkSum byte) (*SignerResponse, error) { if len(blockData) < 3 { return nil, errors.New("begin of structure corrupt") } offset := 0 headerLength := Decode24BitLength(blockData[offset : offset+3]) offset += 3 headerBytes := blockData[offset : offset+headerLength] offset += headerLength content := make([][]byte, 3) for offset < len(blockData) { dataLength := Decode24BitLength(blockData[offset : offset+3]) if len(blockData)-3 < dataLength { return nil, errors.New("structure cut off") } offset += 3 content = append(content, blockData[offset:offset+dataLength]) offset += dataLength } 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 &SignerResponse{ Version: headerBytes[0], Action: shared.Action(headerBytes[1]), Reserved1: headerBytes[2], Reserved2: headerBytes[3], Content: content[0], Argument1: content[1], Argument2: content[2], }, nil } func (r SignerResponse) Serialize() []byte { headerBytes := []byte{r.Version, byte(r.Action), r.Reserved1, r.Reserved2} blockBytes := bytes.Join([][]byte{ Encode24BitLength(headerBytes), headerBytes, Encode24BitLength(r.Content), r.Content, Encode24BitLength(r.Argument1), r.Argument1, Encode24BitLength(r.Argument2), r.Argument2, }, []byte{}) return bytes.Join([][]byte{Encode24BitLength(blockBytes), blockBytes}, []byte{}) } func NewNulResponse(version byte) *SignerResponse { return &SignerResponse{ Version: version, Action: shared.ActionNul, Content: []byte{}, Argument1: []byte{}, Argument2: []byte{}, } } func NewRevokeResponse(version byte, content []byte) *SignerResponse { return &SignerResponse{ Version: version, Action: shared.ActionRevoke, Content: content, Argument1: []byte{}, Argument2: []byte{}, } } func NewSignResponse(version byte, content []byte) *SignerResponse { return &SignerResponse{ Version: version, Action: shared.ActionSign, Content: content, Argument1: []byte{}, Argument2: []byte{}, } }