package datastructures import ( "bytes" "encoding/binary" "fmt" "time" "git.cacert.org/cacert-gosigner/shared" ) const ( headerPosSystem = 2 headerPosRoot = 3 headerPosProfile = 4 headerPosSignatureAlgorithm = 5 headerPosDay = 6 ) type SignerRequest struct { Version uint8 Action shared.Action System shared.CryptoSystemID Root shared.CryptoSystemRootID Profile shared.CertificateProfileID MdAlgorithm shared.SignatureAlgorithmID Days uint16 Spkac uint8 Content1 []byte Content2 []byte Content3 []byte } func SignerRequestFromData(blockData []byte) (*SignerRequest, error) { headerLength := Decode24BitLength(blockData[0:shared.LengthFieldSize]) headerBytes := blockData[shared.LengthFieldSize : shared.LengthFieldSize+headerLength] contentBytes := blockData[shared.LengthFieldSize+headerLength:] contentLen := Decode24BitLength(contentBytes[0:shared.LengthFieldSize]) content := contentBytes[shared.LengthFieldSize : shared.LengthFieldSize+contentLen] argument1Offset := shared.LengthFieldSize + contentLen argument1Len := Decode24BitLength(contentBytes[argument1Offset : argument1Offset+shared.LengthFieldSize]) argument1 := contentBytes[shared.LengthFieldSize+argument1Offset : shared.LengthFieldSize+argument1Offset+argument1Len] argument2Offset := shared.LengthFieldSize + argument1Offset + argument1Len argument2Len := Decode24BitLength(contentBytes[argument2Offset : argument2Offset+shared.LengthFieldSize]) argument2 := contentBytes[shared.LengthFieldSize+argument2Offset : shared.LengthFieldSize+argument2Offset+argument2Len] return &SignerRequest{ Version: headerBytes[headerPosVersion], Action: shared.Action(headerBytes[headerPosAction]), System: shared.CryptoSystemID(headerBytes[headerPosSystem]), Root: shared.CryptoSystemRootID(headerBytes[headerPosRoot]), Profile: shared.CertificateProfileID(headerBytes[headerPosProfile]), MdAlgorithm: shared.SignatureAlgorithmID(headerBytes[headerPosSignatureAlgorithm]), Days: binary.BigEndian.Uint16(headerBytes[headerPosDay : headerPosDay+1]), Spkac: headerBytes[8], Content1: content, Content2: argument1, Content3: argument2, }, nil } func (r *SignerRequest) Serialize() []byte { parameter2Bytes := make([]byte, 2) binary.BigEndian.PutUint16(parameter2Bytes, r.Days) headerBytes := bytes.Join([][]byte{ { r.Version, byte(r.Action), byte(r.System), byte(r.Root), byte(r.Profile), byte(r.MdAlgorithm), }, parameter2Bytes, {r.Spkac}}, []byte{}) content1Bytes := r.Content1 content2Bytes := r.Content2 content3Bytes := 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 (r *SignerRequest) String() string { return fmt.Sprintf( "v:%d %s s:%d r:%d p:%d md:%d days:%d spkac:%d '%s' '%s' '%s'", r.Version, r.Action, r.System, r.Root, r.Profile, r.MdAlgorithm, r.Days, r.Spkac, shorten(r.Content1), shorten(r.Content2), shorten(r.Content3), ) } func shorten(original []byte) []byte { const maxLength = 20 if len(original) > maxLength { return original[:maxLength] } return original } func NewNulRequest() *SignerRequest { return &SignerRequest{ Version: shared.ProtocolVersion, Action: shared.ActionNul, Content1: []byte(time.Now().UTC().Format(signerTimeFormat)), } }