diff --git a/errata.go b/core/errata.go similarity index 100% rename from errata.go rename to core/errata.go diff --git a/core/magic.go b/core/magic.go new file mode 100644 index 0000000..78ae8c1 --- /dev/null +++ b/core/magic.go @@ -0,0 +1,26 @@ +package multihash + +import "errors" + +// ErrSumNotSupported is returned when the Sum function code is not implemented +var ErrSumNotSupported = errors.New("no such hash registered") + +// constants +const ( + IDENTITY = 0x00 + SHA1 = 0x11 + SHA2_256 = 0x12 + SHA2_512 = 0x13 + SHA3_224 = 0x17 + SHA3_256 = 0x16 + SHA3_384 = 0x15 + SHA3_512 = 0x14 + KECCAK_224 = 0x1A + KECCAK_256 = 0x1B + KECCAK_384 = 0x1C + KECCAK_512 = 0x1D + SHAKE_128 = 0x18 + SHAKE_256 = 0x19 + MD5 = 0xd5 + DBL_SHA2_256 = 0x56 +) diff --git a/core/registry.go b/core/registry.go new file mode 100644 index 0000000..64e8af3 --- /dev/null +++ b/core/registry.go @@ -0,0 +1,77 @@ +package multihash + +import ( + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "fmt" + "hash" +) + +// registry is a simple map which maps a multihash indicator number +// to a standard golang Hash interface. +// +// Multihash indicator numbers are reserved and described in +// https://github.com/multiformats/multicodec/blob/master/table.csv . +// The keys used in this map must match those reservations. +// +// Hashers which are available in the golang stdlib will be registered automatically. +// Others can be added using the Register function. +var registry = make(map[uint64]func() hash.Hash) + +// Register adds a new hash to the set available from GetHasher and Sum. +// +// Register has a global effect and should only be used at package init time to avoid data races. +// +// The indicator code should be per the numbers reserved and described in +// https://github.com/multiformats/multicodec/blob/master/table.csv . +// +// If Register is called with the same indicator code more than once, the last call wins. +// In practice, this means that if an application has a strong opinion about what implementation to use for a certain hash +// (e.g., perhaps they want to override the sha256 implementation to use a special hand-rolled assembly variant +// rather than the stdlib one which is registered by default), +// then this can be done by making a Register call with that effect at init time in the application's main package. +// This should have the desired effect because the root of the import tree has its init time effect last. +func Register(indicator uint64, hasherFactory func() hash.Hash) { + if hasherFactory == nil { + panic("not sensible to attempt to register a nil function") + } + registry[indicator] = hasherFactory + DefaultLengths[indicator] = hasherFactory().Size() +} + +// GetHasher returns a new hash.Hash according to the indicator code number provided. +// +// The indicator code should be per the numbers reserved and described in +// https://github.com/multiformats/multicodec/blob/master/table.csv . +// +// The actual hashers available are determined by what has been registered. +// The registry automatically contains those hashers which are available in the golang standard libraries +// (which includes md5, sha1, sha256, sha384, sha512, and the "identity" mulithash, among others). +// Other hash implementations can be made available by using the Register function. +// The 'go-mulithash/register/*' packages can also be imported to gain more common hash functions. +// +// If an error is returned, it will match `errors.Is(err, ErrSumNotSupported)`. +func GetHasher(indicator uint64) (hash.Hash, error) { + factory, exists := registry[indicator] + if !exists { + return nil, fmt.Errorf("unknown multihash code %d (0x%x): %w", indicator, indicator, ErrSumNotSupported) + } + return factory(), nil +} + +// DefaultLengths maps a multihash indicator code to the output size for that hash, in units of bytes. +// +// This map is populated when a hash function is registered by the Register function. +// It's effectively a shortcut for asking Size() on the hash.Hash. +var DefaultLengths = map[uint64]int{} + +func init() { + Register(IDENTITY, func() hash.Hash { return &identityMultihash{} }) + Register(MD5, md5.New) + Register(SHA1, sha1.New) + Register(SHA2_256, sha256.New) + Register(SHA2_512, sha512.New) + Register(DBL_SHA2_256, func() hash.Hash { return &doubleSha256{sha256.New()} }) +} diff --git a/register/blake2/multihash_blake2.go b/register/blake2/multihash_blake2.go index 3d20041..de8f51c 100644 --- a/register/blake2/multihash_blake2.go +++ b/register/blake2/multihash_blake2.go @@ -18,7 +18,7 @@ import ( "github.com/minio/blake2b-simd" "golang.org/x/crypto/blake2s" - "github.com/multiformats/go-multihash" + "github.com/multiformats/go-multihash/core" ) const ( diff --git a/register/miniosha256/multihash_miniosha256.go b/register/miniosha256/multihash_miniosha256.go index 1b9028d..66eccd5 100644 --- a/register/miniosha256/multihash_miniosha256.go +++ b/register/miniosha256/multihash_miniosha256.go @@ -15,7 +15,7 @@ package miniosha256 import ( "github.com/minio/sha256-simd" - "github.com/multiformats/go-multihash" + "github.com/multiformats/go-multihash/core" ) func init() { diff --git a/register/sha3/multihash_sha3.go b/register/sha3/multihash_sha3.go index f8b1692..db70b2b 100644 --- a/register/sha3/multihash_sha3.go +++ b/register/sha3/multihash_sha3.go @@ -18,7 +18,7 @@ import ( "golang.org/x/crypto/sha3" - "github.com/multiformats/go-multihash" + "github.com/multiformats/go-multihash/core" ) func init() { diff --git a/registry.go b/registry.go index 64e8af3..1ca1790 100644 --- a/registry.go +++ b/registry.go @@ -1,77 +1,31 @@ package multihash import ( - "crypto/md5" - "crypto/sha1" - "crypto/sha256" - "crypto/sha512" - "fmt" "hash" -) -// registry is a simple map which maps a multihash indicator number -// to a standard golang Hash interface. -// -// Multihash indicator numbers are reserved and described in -// https://github.com/multiformats/multicodec/blob/master/table.csv . -// The keys used in this map must match those reservations. -// -// Hashers which are available in the golang stdlib will be registered automatically. -// Others can be added using the Register function. -var registry = make(map[uint64]func() hash.Hash) + mhreg "github.com/multiformats/go-multihash/core" -// Register adds a new hash to the set available from GetHasher and Sum. -// -// Register has a global effect and should only be used at package init time to avoid data races. -// -// The indicator code should be per the numbers reserved and described in -// https://github.com/multiformats/multicodec/blob/master/table.csv . + _ "github.com/multiformats/go-multihash/register/all" + _ "github.com/multiformats/go-multihash/register/miniosha256" +) + +// Register is an alias for Register in the core package. // -// If Register is called with the same indicator code more than once, the last call wins. -// In practice, this means that if an application has a strong opinion about what implementation to use for a certain hash -// (e.g., perhaps they want to override the sha256 implementation to use a special hand-rolled assembly variant -// rather than the stdlib one which is registered by default), -// then this can be done by making a Register call with that effect at init time in the application's main package. -// This should have the desired effect because the root of the import tree has its init time effect last. +// Consider using the core package instead of this multihash package; +// that package does not introduce transitive dependencies except for those you opt into, +// and will can result in smaller application builds. func Register(indicator uint64, hasherFactory func() hash.Hash) { - if hasherFactory == nil { - panic("not sensible to attempt to register a nil function") - } - registry[indicator] = hasherFactory - DefaultLengths[indicator] = hasherFactory().Size() + mhreg.Register(indicator, hasherFactory) } -// GetHasher returns a new hash.Hash according to the indicator code number provided. -// -// The indicator code should be per the numbers reserved and described in -// https://github.com/multiformats/multicodec/blob/master/table.csv . -// -// The actual hashers available are determined by what has been registered. -// The registry automatically contains those hashers which are available in the golang standard libraries -// (which includes md5, sha1, sha256, sha384, sha512, and the "identity" mulithash, among others). -// Other hash implementations can be made available by using the Register function. -// The 'go-mulithash/register/*' packages can also be imported to gain more common hash functions. +// Register is an alias for Register in the core package. // -// If an error is returned, it will match `errors.Is(err, ErrSumNotSupported)`. +// Consider using the core package instead of this multihash package; +// that package does not introduce transitive dependencies except for those you opt into, +// and will can result in smaller application builds. func GetHasher(indicator uint64) (hash.Hash, error) { - factory, exists := registry[indicator] - if !exists { - return nil, fmt.Errorf("unknown multihash code %d (0x%x): %w", indicator, indicator, ErrSumNotSupported) - } - return factory(), nil + return mhreg.GetHasher(indicator) } // DefaultLengths maps a multihash indicator code to the output size for that hash, in units of bytes. -// -// This map is populated when a hash function is registered by the Register function. -// It's effectively a shortcut for asking Size() on the hash.Hash. -var DefaultLengths = map[uint64]int{} - -func init() { - Register(IDENTITY, func() hash.Hash { return &identityMultihash{} }) - Register(MD5, md5.New) - Register(SHA1, sha1.New) - Register(SHA2_256, sha256.New) - Register(SHA2_512, sha512.New) - Register(DBL_SHA2_256, func() hash.Hash { return &doubleSha256{sha256.New()} }) -} +var DefaultLengths = mhreg.DefaultLengths diff --git a/sum.go b/sum.go index c18deb1..6d01fe6 100644 --- a/sum.go +++ b/sum.go @@ -3,10 +3,12 @@ package multihash import ( "errors" "fmt" + + mhreg "github.com/multiformats/go-multihash/core" ) // ErrSumNotSupported is returned when the Sum function code is not implemented -var ErrSumNotSupported = errors.New("no such hash registered") +var ErrSumNotSupported = mhreg.ErrSumNotSupported var ErrLenTooLarge = errors.New("requested length was too large for digest")