Как использовать отражение protobuf, чтобы гарантировать детерминированную сериализацию

В Примечания к выпуску Proto3 указано:

Однако детерминированная сериализация НЕ является канонической для разных языков; он также нестабилен в разных сборках с изменениями схемы из-за неизвестных полей. Пользователи, которым нужна каноническая сериализация, например. постоянное хранилище в канонической форме, отпечатки пальцев и т. д. должны определять свою собственную спецификацию канонизации и реализовывать сериализатор с использованием API-интерфейсов отражения, а не полагаться на этот API.

Чего я хотел бы добиться, так это иметь детерминированную сериализацию сообщения protobuf, чтобы нести вместе с ним криптографическую подпись. Насколько я понимаю, из-за различий в сериализаторах двоичные данные могут отличаться, и подпись станет недействительной.

package Something

message Request {
  Payload payload = 1;

  // signature of serialised payload
  bytes signature = 2;

  message Payload {
    string user_id_from = 1;
    uint64 amount = 2;
    string user_id_to = 3;
  }
}

Как это сделать, используя отражение protobuf?


person ischepin    schedule 19.08.2020    source источник


Ответы (1)


Это не отвечает на вопрос напрямую, но может решить вашу проблему: не сохраняйте полезную нагрузку в виде сообщения, а храните сериализованные байты вместе с подписью.

message Request {
  // Serialized Payload message.
  bytes payload = 1;

  // signature of serialised payload
  bytes signature = 2;
}

message Payload {
  string user_id_from = 1;
  uint64 amount = 2;
  string user_id_to = 3;
}

Это может быть немного менее удобно для работы в коде, но имеет то преимущество, что сохраняются все гарантии прямой и обратной совместимости protobuf.

Это также освобождает вас от необходимости дважды сериализовать сообщение при его написании (один раз как подполе, один раз для получения подписи).

person Rafael Lerm    schedule 19.08.2020