A protobuf plugin to generate hash functions for messages.
Hashing messages encoded using Protocol Buffers is tricky because there is no guarantee that the serialized form is stable between different implementations, architectures, or even library versions.
This plugin generates a hash function that does a depth-first traversal of the populated values (including default values) of the message in field number order and feeds it to the provided hash.Hash
implementation. Map values are accessed in key order as well. Because of this deterministic traversal order, the hash generated for two identical protobuf messages should be the same.
NOTE: While we have tested this plugin quite extensively, some edge cases may remain. Use at your own risk.
Download the latest binary for your environment from https://github.com/cerbos/protoc-gen-go-hashpb/releases.
Alternatively, install from source:
go install github.com/cerbos/protoc-gen-go-hashpb@latest
With protoc
:
protoc --plugin protoc-gen-go-hashpb=${GOBIN}/protoc-gen-go-hashpb --go_out=. --go-hashpb_out=. *.proto
func hashMyProto(m *mypb.MyMsg) uint64 {
digest := xxhash.New() // any hash.Hash implementation would work
m.HashPB(digest, nil)
return digest.Sum64()
}
You can exclude certain fields from being included in the hash. The field name must be fully qualified.
ignore := map[string]struct{}{"fully.qualified.package.Message.field_name1": {}, "fully.qualified.package.Message.field_name2":{}}
digest := xxhash.New() // any hash.Hash implementation would work
m.HashPB(digest, ignore)