【问题标题】:Are protobuf Serialize/Parse operations bijective?protobuf 序列化/解析操作是双射的吗?
【发布时间】:2015-04-13 22:21:17
【问题描述】:

我正在编写一个应用程序来计算和验证来自 protobuf 结构的签名。它的计算方式类似于 sign(protobuf_message.SerializeAsString())
我可以确定,相同的protobuf_message 将被相同地序列化(使用不同版本的库(但仅使用 proto2 编码),在不同的计算机上,在不同的条件下),反之亦然?

【问题讨论】:

    标签: c++ protocol-buffers


    【解决方案1】:

    Protobuf documentation 精确定义了二进制消息格式。

    特别是,它说:

    虽然您可以在 .proto 中以任何顺序使用字段编号,但当消息被序列化时其已知字段应按字段编号顺序写入,如提供的 C++、Java 和 Python 序列化代码中一样强>。这允许解析代码使用依赖于按顺序排列的字段编号的优化。但是,protocol buffer 解析器必须能够以任何顺序解析字段,因为并非所有消息都是通过简单地序列化对象来创建的——例如,通过简单地连接它们来合并两条消息有时很有用。

    所以只要你不通过连接其他消息产生新消息,并且使用 protobuf 库本身提供的序列化代码,序列化的消息应该是相同的。如果您正在使用某些第三方 protobuf 绑定(例如用于 C#),您应该检查它是否符合上述建议。

    【讨论】:

    • 请注意,对于一些旧版本的 protobuf 库(例如,在打包数组之前),序列化略有不同。但是对于任何 >= protobuf 2.4 它应该是相同的。我自己有一个测试用例,可以验证相同的编码作为测试 nanopb 的一部分。
    • 在上面引用的段落中有一个很大的警告:它只适用于 known 字段。如果 protobuf 包含任何 unknown 字段(例如,因为它是由较新版本的应用程序编写的,并且现在正在旧版本中处理),则这些字段将以任意顺序附加到末尾(因为正确合并它们会很昂贵)。 proto3 删除了未知字段,但更糟糕的是:删除未知字段显然会改变规范编码。因此,如果您关心签名/规范化,基本上您永远不能向您的原型添加新字段。 ://
    • @jpa 压缩数组不会影响序列化,除非您将 [packed=true] 注释添加到字段,然后总是影响它,因此这只影响规范化,因为更改选项会更改规范形式。只要 protobuf 的定义没有改变,在开源发布之前很久,不同版本的 protobuf 的序列化应该没有区别。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    相关资源
    最近更新 更多