Description
Most hashers in the standard library implement encoding.BinaryMarshaler and encoding.BinaryUnmarshaler. Using those interfaces does make sense in some situations, with the drawback that they won't work with hashers that don't implement them and that it is using encoding methods to clone feels hacky. For example, the Go team at Microsoft maintain some Go bindings for Windows CNG (see repo), and CNG doesn't support serializing the hash internal state.
See https://github.com/search?q=language%3AGo+h.%28encoding.BinaryMarshaler%29&type=code for a none-exhaustive list of projects that use the encoding.BinaryMarshaler
interface.
After analyzing the code of the projects in the list, we found that the encoding.BinaryMarshaler
interface is mostly used in the following ways:
- To serialize the hasher state to disk or to a network connection so that it can be restored later.
- To clone a hasher so that the cloned hasher does not have to recompute the hash over the same data, which might be expensive or even impossible due to the data not being available anymore.
I propose to define an interface that is easier to implement by hash providers:
type Cloner interface {
Hash
Clone() (hash.Hash, error)
}
In addition to the above, we would update all hashers in the stdlib that implement hash.Cloner
.
Examples of projects cloning a hash:
go/src/crypto/tls/handshake_server_tls13.go
Line 436 in 2707d42
- https://github.com/cilium/cilium/blob/f2a025e4eed303ca30ce4c0d993e1af5725b1d77/pkg/crypto/sha1/sha1.go#L53
- https://github.com/cilium/cilium/blob/fd123e413cc60a644194e4af16aff250feb75c4a/pkg/datapath/loader/hash.go#L75
- https://github.com/dedis/dela/blob/7288f632325ab22f27fc57c69d41471dc84df1b5/core/ordering/pow/block.go#L114
- https://github.com/azure-sdk/azure-sdk-for-go/blob/feb133934c75f44918b038aeb62feb67874fe5c3/sdk/containers/azcontainerregistry/digest_helper.go#L110-L119
- https://github.com/SeanHeuc/alist-private-cloud/blob/44a6f4e5605191afac1f67b683a63d0fac8dea4d/pkg/utils/hash/gcid.go#L75