是否有针对不同语言的稳定序列化方法?

时间:2017-08-26 13:56:59

标签: java c++ serialization cryptography protocol-buffers

在我的项目中,我们有一个API,许多客户可能会向此API发送交易。交易应该签署。客户端可以使用任何语言(C ++,C#,python,go,等等)编写,具有任何CPU架构和字节序。

现在的问题是将我们的Transaction模型序列化为字节,以便能够签名然后发送它。

我们的团队为此选择了protobuf v3.3.0(proto syntax = proto3)。

我们想要使用信封图案,它看起来像:

message SignedTransaction {
  message Transaction {/* any data that should be signed */}
  Transaction transaction = 1;
  Signature signature = 2;
}

要签名,我们只是序列化内部对象事务:

Transaction tx = <...>;
std::string bytes = tx.SerializeAsString();
// and then sign bytes

现在protobuf的问题在于它似乎对于不同的语言不是确定性的。今天我们用简单的整数和字符串编写了简单的proto文件,填充了相同的数据,为不同的语言序列化并观察结果。

我们尝试过Javascript,C ++,Java,Swift,结果证明除C ++之外的所有内容都会生成相同的输出字符串:

JavaScript,Java,Swift制作:08B90A10BA0A1A106C6F6C206B656B20636865627572656B

C ++制作:8FFFFFFB9A10FFFFFFBAA1A106C6F6C206B656B20636865627572656B

C ++ parseFromString(str)能够从其他语言反序列化字符串,但反之亦然。

问题是:

  1. 为什么C ++ protobuf产生不同的字符串?
  2. 我们的用例可以使用哪些库?
  3. 详细说明:

    // test.proto:
    syntax = "proto3";
    package api;
    
    message Msg {
        uint32 a = 1;
        int32  b = 2;
        string c = 3;
        bytes  d = 4;
    }
    
    // test.cpp:
    api::Msg msg;
    
    msg.set_a(1337);
    msg.set_b(1338);
    msg.set_c("lol kek cheburek");
    
    std::string str = msg.SerializeAsString();
    // str = 8FFFFFFB9A10FFFFFFBAA1A106C6F6C206B656B20636865627572656B
    

3 个答案:

答案 0 :(得分:1)

what is serialization

我认为protobuf与序列化一词混淆。 protobuf所做的是一种特殊的编码。

除此之外

我怀疑不设置b会导致问题。这意味着b的值未初始化。 java对象是用零自动初始化的,c ++对象没有自动初始化,这意味着内容可能只是随机值。可能发生在b

答案 1 :(得分:1)

原来我打印hexstring的代码中有bug。 details

简短回答: Protobuf是一种稳定的序列化方法,可用于描述的用例。

答案 2 :(得分:0)

Protobuf不稳定,因为可以用不同的方式序列化内存中的同一对象。主要是因为当一个对象具有多个字段时,可以按任何顺序对字段进行序列化。

在此处查看文档:{​​{3}}。