package model import ( "bytes" "errors" "fmt" "go.yandata.net/iod/iod/go-trustlog/api/logger" "go.yandata.net/iod/iod/go-trustlog/internal/helpers" ) // Envelope 包装序列化后的数据,包含元信息和报文体。 // 用于 Trustlog 接口类型的序列化和反序列化。 type Envelope struct { ProducerID string // 日志提供者ID Signature []byte // 签名(根据客户端密钥与指定算法进行签名,二进制格式) Body []byte // CBOR序列化的报文体 } // EnvelopeConfig 序列化配置。 type EnvelopeConfig struct { Signer Signer // 签名器,用于签名和验签 } // VerifyConfig 验签配置。 type VerifyConfig struct { Signer Signer // 签名器,用于验签 } // NewEnvelopeConfig 创建Envelope配置。 func NewEnvelopeConfig(signer Signer) EnvelopeConfig { log := logger.GetGlobalLogger() log.Debug("Creating new EnvelopeConfig", "signerType", fmt.Sprintf("%T", signer), ) return EnvelopeConfig{ Signer: signer, } } // NewSM2EnvelopeConfig 创建使用SM2签名的Envelope配置。 // 便捷方法,用于快速创建SM2签名器配置。 func NewSM2EnvelopeConfig(privateKey, publicKey []byte) EnvelopeConfig { log := logger.GetGlobalLogger() log.Debug("Creating new SM2 EnvelopeConfig", "privateKeyLength", len(privateKey), "publicKeyLength", len(publicKey), ) return EnvelopeConfig{ Signer: NewSM2Signer(privateKey, publicKey), } } // NewVerifyConfig 创建验签配置。 func NewVerifyConfig(signer Signer) VerifyConfig { log := logger.GetGlobalLogger() log.Debug("Creating new VerifyConfig", "signerType", fmt.Sprintf("%T", signer), ) return VerifyConfig{ Signer: signer, } } // NewSM2VerifyConfig 创建使用SM2签名的验签配置。 // 便捷方法,用于快速创建SM2签名器验签配置。 // 注意:验签只需要公钥,但SM2Signer需要同时提供私钥和公钥(私钥可以为空)。 func NewSM2VerifyConfig(publicKey []byte) VerifyConfig { return VerifyConfig{ Signer: NewSM2Signer(nil, publicKey), } } // // ===== Envelope 序列化/反序列化 ===== // // MarshalEnvelope 将 Envelope 序列化为 TLV 格式(Varint长度编码)。 // 格式:[字段1长度][字段1值:producerID][字段2长度][字段2值:签名][字段3长度][字段3值:CBOR报文体]。 func MarshalEnvelope(env *Envelope) ([]byte, error) { log := logger.GetGlobalLogger() log.Debug("Marshaling envelope to TLV format") if env == nil { log.Error("Envelope is nil") return nil, errors.New("envelope cannot be nil") } buf := new(bytes.Buffer) writer := helpers.NewTLVWriter(buf) log.Debug("Writing producerID to TLV", "producerID", env.ProducerID, ) if err := writer.WriteStringField(env.ProducerID); err != nil { log.Error("Failed to write producerID", "error", err, "producerID", env.ProducerID, ) return nil, fmt.Errorf("failed to write producerID: %w", err) } log.Debug("Writing signature to TLV", "signatureLength", len(env.Signature), ) if err := writer.WriteField(env.Signature); err != nil { log.Error("Failed to write signature", "error", err, "signatureLength", len(env.Signature), ) return nil, fmt.Errorf("failed to write signature: %w", err) } log.Debug("Writing body to TLV", "bodyLength", len(env.Body), ) if err := writer.WriteField(env.Body); err != nil { log.Error("Failed to write body", "error", err, "bodyLength", len(env.Body), ) return nil, fmt.Errorf("failed to write body: %w", err) } result := buf.Bytes() log.Debug("Envelope marshaled successfully", "producerID", env.ProducerID, "totalLength", len(result), ) return result, nil } // UnmarshalEnvelope 完整反序列化:读取所有字段。 // 解析完整的Envelope结构,包括所有元数据和Body。 // 为了向后兼容,如果遇到旧格式(包含原hash字段),会自动跳过该字段。 func UnmarshalEnvelope(data []byte) (*Envelope, error) { log := logger.GetGlobalLogger() log.Debug("Unmarshaling envelope from TLV format", "dataLength", len(data), ) if len(data) == 0 { log.Error("Data is empty") return nil, errors.New("data is empty") } r := bytes.NewReader(data) reader := helpers.NewTLVReader(r) log.Debug("Reading producerID from TLV") producerID, err := reader.ReadStringField() if err != nil { log.Error("Failed to read producerID", "error", err, ) return nil, fmt.Errorf("failed to read producerID: %w", err) } log.Debug("ProducerID read successfully", "producerID", producerID, ) // 读取第一个字段(可能是原hash或签名) log.Debug("Reading field 1 from TLV") field1, err := reader.ReadField() if err != nil { log.Error("Failed to read field 1", "error", err, ) return nil, fmt.Errorf("failed to read field 1: %w", err) } log.Debug("Field 1 read successfully", "field1Length", len(field1), ) // 读取第二个字段(可能是签名或body) log.Debug("Reading field 2 from TLV") field2, err := reader.ReadField() if err != nil { log.Error("Failed to read field 2", "error", err, ) return nil, fmt.Errorf("failed to read field 2: %w", err) } log.Debug("Field 2 read successfully", "field2Length", len(field2), ) // 尝试读取第三个字段来判断格式 log.Debug("Attempting to read field 3 to determine format") field3, err := reader.ReadField() if err == nil { // 有第三个字段,说明是旧格式:producerID, originalHash, encryptedHash, body // field1 = originalHash, field2 = encryptedHash/signature, field3 = body log.Debug("Detected old format (with originalHash)", "producerID", producerID, "signatureLength", len(field2), "bodyLength", len(field3), ) return &Envelope{ ProducerID: producerID, Signature: field2, Body: field3, }, nil } // 没有第三个字段,说明是新格式:producerID, signature, body // field1 = signature, field2 = body log.Debug("Detected new format (without originalHash)", "producerID", producerID, "signatureLength", len(field1), "bodyLength", len(field2), ) return &Envelope{ ProducerID: producerID, Signature: field1, Body: field2, }, nil } // // ===== 部分反序列化(无需反序列化全部报文) ===== // // UnmarshalEnvelopeProducerID 部分反序列化:只读取字段1(producerID)。 // 用于快速获取producerID而不解析整个Envelope。 func UnmarshalEnvelopeProducerID(data []byte) (string, error) { if len(data) == 0 { return "", errors.New("data is empty") } r := bytes.NewReader(data) reader := helpers.NewTLVReader(r) producerID, err := reader.ReadStringField() if err != nil { return "", fmt.Errorf("failed to read producerID: %w", err) } return producerID, nil } // UnmarshalEnvelopeSignature 部分反序列化:读取字段1、2(producerID, 签名)。 // 用于获取签名信息而不解析整个Body。 // 为了向后兼容,如果遇到旧格式(包含原hash字段),会自动跳过该字段。 func UnmarshalEnvelopeSignature(data []byte) (string, []byte, error) { if len(data) == 0 { return "", nil, errors.New("data is empty") } r := bytes.NewReader(data) reader := helpers.NewTLVReader(r) producerID, err := reader.ReadStringField() if err != nil { return "", nil, fmt.Errorf("failed to read producerID: %w", err) } // 读取第一个字段(可能是原hash或签名) field1, err := reader.ReadField() if err != nil { return "", nil, fmt.Errorf("failed to read field 1: %w", err) } // 读取第二个字段(可能是签名或body) field2, err := reader.ReadField() if err != nil { return "", nil, fmt.Errorf("failed to read field 2: %w", err) } // 尝试读取第三个字段来判断格式 _, err = reader.ReadField() if err == nil { // 有第三个字段,说明是旧格式:producerID, originalHash, encryptedHash/signature, body // field1 = originalHash, field2 = signature return producerID, field2, nil } // 没有第三个字段,说明是新格式:producerID, signature, body // field1 = signature return producerID, field1, nil } // // ===== Trustlog 序列化/反序列化 ===== // // MarshalTrustlog 序列化 Trustlog 为 Envelope 格式。 // Trustlog 实现了 Trustlog 接口,自动提取 producerID 并使用 Canonical CBOR 编码。 func MarshalTrustlog(t Trustlog, config EnvelopeConfig) ([]byte, error) { log := logger.GetGlobalLogger() log.Debug("Marshaling Trustlog to Envelope format", "trustlogType", fmt.Sprintf("%T", t), ) if t == nil { log.Error("Trustlog is nil") return nil, errors.New("trustlog cannot be nil") } producerID := t.GetProducerID() if producerID == "" { log.Error("ProducerID is empty") return nil, errors.New("producerID cannot be empty") } log.Debug("ProducerID extracted", "producerID", producerID, ) // 1. 序列化CBOR报文体(使用 Trustlog 的 MarshalBinary,确保使用 Canonical CBOR) log.Debug("Marshaling trustlog to CBOR binary") bodyCBOR, err := t.MarshalBinary() if err != nil { log.Error("Failed to marshal trustlog to CBOR", "error", err, "producerID", producerID, ) return nil, fmt.Errorf("failed to marshal trustlog: %w", err) } log.Debug("Trustlog marshaled to CBOR successfully", "producerID", producerID, "bodyLength", len(bodyCBOR), ) // 2. 计算签名 if config.Signer == nil { log.Error("Signer is nil") return nil, errors.New("signer is required") } log.Debug("Signing trustlog body", "producerID", producerID, "bodyLength", len(bodyCBOR), ) signature, err := config.Signer.Sign(bodyCBOR) if err != nil { log.Error("Failed to sign trustlog body", "error", err, "producerID", producerID, ) return nil, fmt.Errorf("failed to sign data: %w", err) } log.Debug("Trustlog body signed successfully", "producerID", producerID, "signatureLength", len(signature), ) // 3. 构建Envelope env := &Envelope{ ProducerID: producerID, Signature: signature, Body: bodyCBOR, } // 4. 序列化为TLV格式 log.Debug("Marshaling envelope to TLV format", "producerID", producerID, ) return MarshalEnvelope(env) } // UnmarshalTrustlog 反序列化 Envelope 为 Trustlog。 // 解析Envelope数据并恢复 Trustlog 结构。 func UnmarshalTrustlog(data []byte, t Trustlog) error { log := logger.GetGlobalLogger() log.Debug("Unmarshaling Envelope to Trustlog", "trustlogType", fmt.Sprintf("%T", t), "dataLength", len(data), ) if t == nil { log.Error("Trustlog is nil") return errors.New("trustlog cannot be nil") } env, err := UnmarshalEnvelope(data) if err != nil { log.Error("Failed to unmarshal envelope", "error", err, ) return err } log.Debug("Envelope unmarshaled successfully", "producerID", env.ProducerID, "bodyLength", len(env.Body), ) // 使用 Trustlog 的 UnmarshalBinary 反序列化 log.Debug("Unmarshaling trustlog body from CBOR", "producerID", env.ProducerID, ) if errUnmarshal := t.UnmarshalBinary(env.Body); errUnmarshal != nil { log.Error("Failed to unmarshal trustlog body", "error", errUnmarshal, "producerID", env.ProducerID, ) return fmt.Errorf("failed to unmarshal trustlog body: %w", errUnmarshal) } log.Debug("Trustlog unmarshaled successfully", "producerID", env.ProducerID, ) return nil } // // ===== Operation 序列化/反序列化 ===== // // MarshalOperation 序列化 Operation 为 Envelope 格式。 func MarshalOperation(op *Operation, config EnvelopeConfig) ([]byte, error) { return MarshalTrustlog(op, config) } // UnmarshalOperation 反序列化 Envelope 为 Operation。 func UnmarshalOperation(data []byte) (*Operation, error) { var op Operation if err := UnmarshalTrustlog(data, &op); err != nil { return nil, err } return &op, nil } // // ===== Record 序列化/反序列化 ===== // // MarshalRecord 序列化 Record 为 Envelope 格式。 func MarshalRecord(record *Record, config EnvelopeConfig) ([]byte, error) { return MarshalTrustlog(record, config) } // UnmarshalRecord 反序列化 Envelope 为 Record。 func UnmarshalRecord(data []byte) (*Record, error) { var record Record if err := UnmarshalTrustlog(data, &record); err != nil { return nil, err } return &record, nil } // // ===== 验证 ===== // // VerifyEnvelope 验证Envelope的完整性(使用EnvelopeConfig)。 // 验证签名是否匹配,确保数据未被篡改。 // 如果验证成功,返回解析后的Envelope结构体指针;如果验证失败,返回错误。 func VerifyEnvelope(data []byte, config EnvelopeConfig) (*Envelope, error) { if config.Signer == nil { return nil, errors.New("signer is required for verification") } verifyConfig := VerifyConfig(config) return VerifyEnvelopeWithConfig(data, verifyConfig) } // VerifyEnvelopeWithConfig 验证Envelope的完整性(使用VerifyConfig)。 // 验证签名是否匹配,确保数据未被篡改。 // 如果验证成功,返回解析后的Envelope结构体指针;如果验证失败,返回错误。 func VerifyEnvelopeWithConfig(data []byte, config VerifyConfig) (*Envelope, error) { log := logger.GetGlobalLogger() log.Debug("Verifying envelope", "dataLength", len(data), ) if config.Signer == nil { log.Error("Signer is nil") return nil, errors.New("signer is required for verification") } env, err := UnmarshalEnvelope(data) if err != nil { log.Error("Failed to unmarshal envelope", "error", err, ) return nil, fmt.Errorf("failed to unmarshal envelope: %w", err) } log.Debug("Envelope unmarshaled for verification", "producerID", env.ProducerID, "bodyLength", len(env.Body), "signatureLength", len(env.Signature), ) // 验证签名 log.Debug("Verifying signature", "producerID", env.ProducerID, ) valid, err := config.Signer.Verify(env.Body, env.Signature) if err != nil { log.Error("Failed to verify signature", "error", err, "producerID", env.ProducerID, ) return nil, fmt.Errorf("failed to verify signature: %w", err) } if !valid { log.Warn("Signature verification failed", "producerID", env.ProducerID, ) return nil, errors.New("signature verification failed") } log.Debug("Envelope verified successfully", "producerID", env.ProducerID, ) return env, nil }