pax_global_header00006660000000000000000000000064144415467310014523gustar00rootroot0000000000000052 comment=ff9da31500dddfc675e996601a05cdfc3ce7c764 go-multihash-0.2.3/000077500000000000000000000000001444154673100141265ustar00rootroot00000000000000go-multihash-0.2.3/.github/000077500000000000000000000000001444154673100154665ustar00rootroot00000000000000go-multihash-0.2.3/.github/workflows/000077500000000000000000000000001444154673100175235ustar00rootroot00000000000000go-multihash-0.2.3/.github/workflows/automerge.yml000066400000000000000000000003761444154673100222440ustar00rootroot00000000000000# File managed by web3-bot. DO NOT EDIT. # See https://github.com/protocol/.github/ for details. name: Automerge on: [ pull_request ] jobs: automerge: uses: protocol/.github/.github/workflows/automerge.yml@master with: job: 'automerge' go-multihash-0.2.3/.github/workflows/go-check.yml000066400000000000000000000047111444154673100217310ustar00rootroot00000000000000# File managed by web3-bot. DO NOT EDIT. # See https://github.com/protocol/.github/ for details. on: [push, pull_request] name: Go Checks jobs: unit: runs-on: ubuntu-latest name: All steps: - uses: actions/checkout@v3 with: submodules: recursive - id: config uses: protocol/.github/.github/actions/read-config@master - uses: actions/setup-go@v3 with: go-version: 1.20.x - name: Run repo-specific setup uses: ./.github/actions/go-check-setup if: hashFiles('./.github/actions/go-check-setup') != '' - name: Install staticcheck run: go install honnef.co/go/tools/cmd/staticcheck@4970552d932f48b71485287748246cf3237cebdf # 2023.1 (v0.4.0) - name: Check that go.mod is tidy uses: protocol/multiple-go-modules@v1.2 with: run: | go mod tidy if [[ -n $(git ls-files --other --exclude-standard --directory -- go.sum) ]]; then echo "go.sum was added by go mod tidy" exit 1 fi git diff --exit-code -- go.sum go.mod - name: gofmt if: success() || failure() # run this step even if the previous one failed run: | out=$(gofmt -s -l .) if [[ -n "$out" ]]; then echo $out | awk '{print "::error file=" $0 ",line=0,col=0::File is not gofmt-ed."}' exit 1 fi - name: go vet if: success() || failure() # run this step even if the previous one failed uses: protocol/multiple-go-modules@v1.2 with: run: go vet ./... - name: staticcheck if: success() || failure() # run this step even if the previous one failed uses: protocol/multiple-go-modules@v1.2 with: run: | set -o pipefail staticcheck ./... | sed -e 's@\(.*\)\.go@./\1.go@g' - name: go generate uses: protocol/multiple-go-modules@v1.2 if: (success() || failure()) && fromJSON(steps.config.outputs.json).gogenerate == true with: run: | git clean -fd # make sure there aren't untracked files / directories go generate -x ./... # check if go generate modified or added any files if ! $(git add . && git diff-index HEAD --exit-code --quiet); then echo "go generated caused changes to the repository:" git status --short exit 1 fi go-multihash-0.2.3/.github/workflows/go-test.yml000066400000000000000000000060341444154673100216330ustar00rootroot00000000000000# File managed by web3-bot. DO NOT EDIT. # See https://github.com/protocol/.github/ for details. on: [push, pull_request] name: Go Test jobs: unit: strategy: fail-fast: false matrix: os: [ "ubuntu", "windows", "macos" ] go: ["1.19.x","1.20.x"] env: COVERAGES: "" runs-on: ${{ fromJSON(vars[format('UCI_GO_TEST_RUNNER_{0}', matrix.os)] || format('"{0}-latest"', matrix.os)) }} name: ${{ matrix.os }} (go ${{ matrix.go }}) steps: - uses: actions/checkout@v3 with: submodules: recursive - id: config uses: protocol/.github/.github/actions/read-config@master - uses: actions/setup-go@v3 with: go-version: ${{ matrix.go }} - name: Go information run: | go version go env - name: Use msys2 on windows if: matrix.os == 'windows' shell: bash # The executable for msys2 is also called bash.cmd # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#shells # If we prepend its location to the PATH # subsequent 'shell: bash' steps will use msys2 instead of gitbash run: echo "C:/msys64/usr/bin" >> $GITHUB_PATH - name: Run repo-specific setup uses: ./.github/actions/go-test-setup if: hashFiles('./.github/actions/go-test-setup') != '' - name: Run tests if: contains(fromJSON(steps.config.outputs.json).skipOSes, matrix.os) == false uses: protocol/multiple-go-modules@v1.2 with: # Use -coverpkg=./..., so that we include cross-package coverage. # If package ./A imports ./B, and ./A's tests also cover ./B, # this means ./B's coverage will be significantly higher than 0%. run: go test -v -shuffle=on -coverprofile=module-coverage.txt -coverpkg=./... ./... - name: Run tests (32 bit) # can't run 32 bit tests on OSX. if: matrix.os != 'macos' && fromJSON(steps.config.outputs.json).skip32bit != true && contains(fromJSON(steps.config.outputs.json).skipOSes, matrix.os) == false uses: protocol/multiple-go-modules@v1.2 env: GOARCH: 386 with: run: | export "PATH=$PATH_386:$PATH" go test -v -shuffle=on ./... - name: Run tests with race detector # speed things up. Windows and OSX VMs are slow if: matrix.os == 'ubuntu' && contains(fromJSON(steps.config.outputs.json).skipOSes, matrix.os) == false uses: protocol/multiple-go-modules@v1.2 with: run: go test -v -race ./... - name: Collect coverage files shell: bash run: echo "COVERAGES=$(find . -type f -name 'module-coverage.txt' | tr -s '\n' ',' | sed 's/,$//')" >> $GITHUB_ENV - name: Upload coverage to Codecov uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 with: files: '${{ env.COVERAGES }}' env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} go-multihash-0.2.3/.github/workflows/release-check.yml000066400000000000000000000004621444154673100227430ustar00rootroot00000000000000# File managed by web3-bot. DO NOT EDIT. # See https://github.com/protocol/.github/ for details. name: Release Checker on: pull_request_target: paths: [ 'version.json' ] jobs: release-check: uses: protocol/.github/.github/workflows/release-check.yml@master with: go-version: 1.20.x go-multihash-0.2.3/.github/workflows/releaser.yml000066400000000000000000000003571444154673100220550ustar00rootroot00000000000000# File managed by web3-bot. DO NOT EDIT. # See https://github.com/protocol/.github/ for details. name: Releaser on: push: paths: [ 'version.json' ] jobs: releaser: uses: protocol/.github/.github/workflows/releaser.yml@master go-multihash-0.2.3/.github/workflows/tagpush.yml000066400000000000000000000003551444154673100217240ustar00rootroot00000000000000# File managed by web3-bot. DO NOT EDIT. # See https://github.com/protocol/.github/ for details. name: Tag Push Checker on: push: tags: - v* jobs: releaser: uses: protocol/.github/.github/workflows/tagpush.yml@master go-multihash-0.2.3/.gitignore000066400000000000000000000000111444154673100161060ustar00rootroot00000000000000.vscode/ go-multihash-0.2.3/.gitmodules000066400000000000000000000003251444154673100163030ustar00rootroot00000000000000[submodule "spec/multicodec"] path = spec/multicodec url = https://github.com/multiformats/multicodec.git [submodule "spec/multihash"] path = spec/multihash url = https://github.com/multiformats/multihash.git go-multihash-0.2.3/.gx/000077500000000000000000000000001444154673100146225ustar00rootroot00000000000000go-multihash-0.2.3/.gx/lastpubver000066400000000000000000000000671444154673100167370ustar00rootroot000000000000001.0.10: QmaENCY6u1328TiL3BozJLgZJxCh7oNJpMnUpgcDyX8TWp go-multihash-0.2.3/LICENSE000066400000000000000000000020731444154673100151350ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2014 Juan Batiz-Benet Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. go-multihash-0.2.3/README.md000066400000000000000000000064061444154673100154130ustar00rootroot00000000000000# go-multihash [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/project-multiformats-blue.svg?style=flat-square)](https://github.com/multiformats/multiformats) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23ipfs) [![](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) [![GoDoc](https://godoc.org/github.com/multiformats/go-multihash?status.svg)](https://godoc.org/github.com/multiformats/go-multihash) [![Travis CI](https://img.shields.io/travis/multiformats/go-multihash.svg?style=flat-square&branch=master)](https://travis-ci.org/multiformats/go-multihash) [![codecov.io](https://img.shields.io/codecov/c/github/multiformats/go-multihash.svg?style=flat-square&branch=master)](https://codecov.io/github/multiformats/go-multihash?branch=master) > [multihash](https://github.com/multiformats/multihash) implementation in Go ## Table of Contents - [Install](#install) - [Usage](#usage) - [Maintainers](#maintainers) - [Contribute](#contribute) - [License](#license) ## Install `go-multihash` is a standard Go module which can be installed with: ```sh go get github.com/multiformats/go-multihash ``` ## Usage ### Example This example takes a standard hex-encoded data and uses `EncodeName` to calculate the SHA1 multihash value for the buffer. The resulting hex-encoded data corresponds to: ``, which could be re-parsed with `Multihash.FromHexString()`. ```go package main import ( "encoding/hex" "fmt" "github.com/multiformats/go-multihash" ) func main() { // ignores errors for simplicity. // don't do that at home. // Decode a SHA1 hash to a binary buffer buf, _ := hex.DecodeString("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33") // Create a new multihash with it. mHashBuf, _ := multihash.EncodeName(buf, "sha1") // Print the multihash as hex string fmt.Printf("hex: %s\n", hex.EncodeToString(mHashBuf)) // Parse the binary multihash to a DecodedMultihash mHash, _ := multihash.Decode(mHashBuf) // Convert the sha1 value to hex string sha1hex := hex.EncodeToString(mHash.Digest) // Print all the information in the multihash fmt.Printf("obj: %v 0x%x %d %s\n", mHash.Name, mHash.Code, mHash.Length, sha1hex) } ``` To run, copy to [example/foo.go](example/foo.go) and: ``` > cd example/ > go build > ./example hex: 11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33 obj: sha1 0x11 20 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33 ``` ## Contribute Contributions welcome. Please check out [the issues](https://github.com/multiformats/go-multihash/issues). Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. ## License [MIT](LICENSE) © 2014 Juan Batiz-Benet go-multihash-0.2.3/allocate_go119_test.go000066400000000000000000000004471444154673100202250ustar00rootroot00000000000000//go:build !go1.20 package multihash import "testing" func mustNotAllocateMore(_ *testing.T, _ float64, f func()) { // the compiler isn't able to detect our outlined stack allocation on before // 1.20 so let's not test for it. We don't mind if outdated versions are slightly slower. f() } go-multihash-0.2.3/allocate_go120_test.go000066400000000000000000000003421444154673100202070ustar00rootroot00000000000000//go:build go1.20 package multihash import "testing" func mustNotAllocateMore(t *testing.T, n float64, f func()) { t.Helper() if b := testing.AllocsPerRun(10, f); b > n { t.Errorf("it allocated %f max %f !", b, n) } } go-multihash-0.2.3/codecov.yml000066400000000000000000000000531444154673100162710ustar00rootroot00000000000000coverage: range: "50...100" comment: off go-multihash-0.2.3/core/000077500000000000000000000000001444154673100150565ustar00rootroot00000000000000go-multihash-0.2.3/core/errata.go000066400000000000000000000012451444154673100166650ustar00rootroot00000000000000package multihash import ( "bytes" "crypto/sha256" "hash" ) type identityMultihash struct { bytes.Buffer } func (identityMultihash) BlockSize() int { return 32 // A prefered block size is nonsense for the "identity" "hash". An arbitrary but unsurprising and positive nonzero number has been chosen to minimize the odds of fascinating bugs. } func (x *identityMultihash) Size() int { return x.Len() } func (x *identityMultihash) Sum(digest []byte) []byte { return x.Bytes() } type doubleSha256 struct { hash.Hash } func (x doubleSha256) Sum(digest []byte) []byte { digest = x.Hash.Sum(digest) h2 := sha256.New() h2.Write(digest) return h2.Sum(digest[0:0]) } go-multihash-0.2.3/core/magic.go000066400000000000000000000015451444154673100164720ustar00rootroot00000000000000package multihash import "errors" // ErrSumNotSupported is returned when the Sum function code is not implemented var ErrSumNotSupported = errors.New("no such hash registered") // ErrLenTooLarge is returned when the hash function cannot produce the requested number of bytes var ErrLenTooLarge = errors.New("requested length was too large for digest") // constants const ( IDENTITY = 0x00 SHA1 = 0x11 SHA2_224 = 0x1013 SHA2_256 = 0x12 SHA2_384 = 0x20 SHA2_512 = 0x13 SHA2_512_224 = 0x1014 SHA2_512_256 = 0x1015 SHA3_224 = 0x17 SHA3_256 = 0x16 SHA3_384 = 0x15 SHA3_512 = 0x14 KECCAK_224 = 0x1A KECCAK_256 = 0x1B KECCAK_384 = 0x1C KECCAK_512 = 0x1D BLAKE3 = 0x1E SHAKE_128 = 0x18 SHAKE_256 = 0x19 MURMUR3X64_64 = 0x22 MD5 = 0xd5 DBL_SHA2_256 = 0x56 ) go-multihash-0.2.3/core/registry.go000066400000000000000000000121001444154673100172470ustar00rootroot00000000000000package 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 function : (size:int) -> ((hasher:hash.Hash), (bool:success)) // The function may error (i.e., return (nil, false)) to signify that the hasher can't return that many bytes. // // 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(int) (h hash.Hash, ok bool)) // 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") } maxSize := hasherFactory().Size() registry[indicator] = func(size int) (hash.Hash, bool) { if size > maxSize { return nil, false } return hasherFactory(), true } DefaultLengths[indicator] = maxSize } // RegisterVariableSize is like Register, but adds a new variable-sized hasher factory that takes a // size hint. // // When passed -1, the hasher should produce digests with the hash-function's default length. When // passed a non-negative integer, the hasher should try to produce digests of at least the specified // size. func RegisterVariableSize(indicator uint64, hasherFactory func(sizeHint int) (hash.Hash, bool)) { if hasherFactory == nil { panic("not sensible to attempt to register a nil function") } if hasher, ok := hasherFactory(-1); !ok { panic("failed to determine default hash length for hasher") } else { DefaultLengths[indicator] = hasher.Size() } registry[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. // // If an error is returned, it will match `errors.Is(err, ErrSumNotSupported)`. func GetHasher(indicator uint64) (hash.Hash, error) { return GetVariableHasher(indicator, -1) } // GetVariableHasher returns a new hash.Hash according to the indicator code number provided, with // the specified size hint. // // NOTE: The size hint is only a hint. Hashers will attempt to produce at least the number of requested bytes, but may not. // // This function can fail if either the hash code is not registered, or the passed size hint is // statically incompatible with the specified hash function. func GetVariableHasher(indicator uint64, sizeHint int) (hash.Hash, error) { factory, exists := registry[indicator] if !exists { return nil, fmt.Errorf("unknown multihash code %d (0x%x): %w", indicator, indicator, ErrSumNotSupported) } hasher, ok := factory(sizeHint) if !ok { return nil, ErrLenTooLarge } return hasher, 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() { RegisterVariableSize(IDENTITY, func(_ int) (hash.Hash, bool) { return &identityMultihash{}, true }) Register(MD5, md5.New) Register(SHA1, sha1.New) Register(SHA2_224, sha256.New224) Register(SHA2_256, sha256.New) Register(SHA2_384, sha512.New384) Register(SHA2_512, sha512.New) Register(SHA2_512_224, sha512.New512_224) Register(SHA2_512_256, sha512.New512_256) Register(DBL_SHA2_256, func() hash.Hash { return &doubleSha256{sha256.New()} }) } go-multihash-0.2.3/go.mod000066400000000000000000000006241444154673100152360ustar00rootroot00000000000000module github.com/multiformats/go-multihash require ( github.com/minio/sha256-simd v1.0.0 github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-varint v0.0.6 github.com/spaolacci/murmur3 v1.1.0 golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e lukechampine.com/blake3 v1.1.6 ) require ( github.com/klauspost/cpuid/v2 v2.0.9 // indirect golang.org/x/sys v0.1.0 // indirect ) go 1.19 go-multihash-0.2.3/go.sum000066400000000000000000000027361444154673100152710ustar00rootroot00000000000000github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= lukechampine.com/blake3 v1.1.6 h1:H3cROdztr7RCfoaTpGZFQsrqvweFLrqS73j7L7cmR5c= lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= go-multihash-0.2.3/io.go000066400000000000000000000035621444154673100150720ustar00rootroot00000000000000package multihash import ( "errors" "io" "math" "github.com/multiformats/go-varint" ) // Reader is an io.Reader wrapper that exposes a function // to read a whole multihash, parse it, and return it. type Reader interface { io.Reader ReadMultihash() (Multihash, error) } // Writer is an io.Writer wrapper that exposes a function // to write a whole multihash. type Writer interface { io.Writer WriteMultihash(Multihash) error } // NewReader wraps an io.Reader with a multihash.Reader func NewReader(r io.Reader) Reader { return &mhReader{r} } // NewWriter wraps an io.Writer with a multihash.Writer func NewWriter(w io.Writer) Writer { return &mhWriter{w} } type mhReader struct { r io.Reader } func (r *mhReader) Read(buf []byte) (n int, err error) { return r.r.Read(buf) } func (r *mhReader) ReadByte() (byte, error) { if br, ok := r.r.(io.ByteReader); ok { return br.ReadByte() } var b [1]byte n, err := r.r.Read(b[:]) if n == 1 { return b[0], nil } if err == nil { if n != 0 { panic("reader returned an invalid length") } err = io.ErrNoProgress } return 0, err } func (r *mhReader) ReadMultihash() (Multihash, error) { code, err := varint.ReadUvarint(r) if err != nil { return nil, err } length, err := varint.ReadUvarint(r) if err != nil { return nil, err } if length > math.MaxInt32 { return nil, errors.New("digest too long, supporting only <= 2^31-1") } buf := make([]byte, varint.UvarintSize(code)+varint.UvarintSize(length)+int(length)) n := varint.PutUvarint(buf, code) n += varint.PutUvarint(buf[n:], length) if _, err := io.ReadFull(r.r, buf[n:]); err != nil { return nil, err } return Cast(buf) } type mhWriter struct { w io.Writer } func (w *mhWriter) Write(buf []byte) (n int, err error) { return w.w.Write(buf) } func (w *mhWriter) WriteMultihash(m Multihash) error { _, err := w.w.Write([]byte(m)) return err } go-multihash-0.2.3/io_test.go000066400000000000000000000030711444154673100161240ustar00rootroot00000000000000package multihash import ( "bytes" "io" "testing" ) type evilReader struct { buffer []byte } func (er *evilReader) Read(buf []byte) (int, error) { n := copy(buf, er.buffer) er.buffer = er.buffer[n:] var err error if len(er.buffer) == 0 { err = io.EOF } return n, err } func TestEvilReader(t *testing.T) { emptyHash, err := Sum(nil, IDENTITY, 0) if err != nil { t.Fatal(err) } r := NewReader(&evilReader{emptyHash}) h, err := r.ReadMultihash() if err != nil { t.Fatal(err) } if !bytes.Equal(h, []byte(emptyHash)) { t.Fatal(err) } h, err = r.ReadMultihash() if len([]byte(h)) > 0 || err != io.EOF { t.Fatal("expected end of file") } } func TestReader(t *testing.T) { var buf bytes.Buffer for _, tc := range testCases { m, err := tc.Multihash() if err != nil { t.Fatal(err) } buf.Write([]byte(m)) } r := NewReader(&buf) for _, tc := range testCases { h, err := tc.Multihash() if err != nil { t.Fatal(err) } h2, err := r.ReadMultihash() if err != nil { t.Error(err) continue } if !bytes.Equal(h, h2) { t.Error("h and h2 should be equal") } } } func TestWriter(t *testing.T) { var buf bytes.Buffer w := NewWriter(&buf) for _, tc := range testCases { m, err := tc.Multihash() if err != nil { t.Error(err) continue } if err := w.WriteMultihash(m); err != nil { t.Error(err) continue } buf2 := make([]byte, len(m)) if _, err := io.ReadFull(&buf, buf2); err != nil { t.Error(err) continue } if !bytes.Equal(m, buf2) { t.Error("m and buf2 should be equal") } } } go-multihash-0.2.3/multihash.go000066400000000000000000000216611444154673100164610ustar00rootroot00000000000000// Package multihash is the Go implementation of // https://github.com/multiformats/multihash, or self-describing // hashes. package multihash import ( "encoding/hex" "errors" "fmt" "math" b58 "github.com/mr-tron/base58/base58" "github.com/multiformats/go-varint" ) // errors var ( ErrUnknownCode = errors.New("unknown multihash code") ErrTooShort = errors.New("multihash too short. must be >= 2 bytes") ErrTooLong = errors.New("multihash too long. must be < 129 bytes") ErrLenNotSupported = errors.New("multihash does not yet support digests longer than 127 bytes") ErrInvalidMultihash = errors.New("input isn't valid multihash") ErrVarintBufferShort = errors.New("uvarint: buffer too small") ErrVarintTooLong = errors.New("uvarint: varint too big (max 64bit)") ) // ErrInconsistentLen is returned when a decoded multihash has an inconsistent length type ErrInconsistentLen struct { dm DecodedMultihash lengthFound int } func (e ErrInconsistentLen) Error() string { return fmt.Sprintf("multihash length inconsistent: expected %d; got %d", e.dm.Length, e.lengthFound) } // constants const ( IDENTITY = 0x00 // Deprecated: use IDENTITY ID = IDENTITY SHA1 = 0x11 SHA2_256 = 0x12 SHA2_512 = 0x13 SHA3_224 = 0x17 SHA3_256 = 0x16 SHA3_384 = 0x15 SHA3_512 = 0x14 SHA3 = SHA3_512 KECCAK_224 = 0x1A KECCAK_256 = 0x1B KECCAK_384 = 0x1C KECCAK_512 = 0x1D BLAKE3 = 0x1E SHAKE_128 = 0x18 SHAKE_256 = 0x19 BLAKE2B_MIN = 0xb201 BLAKE2B_MAX = 0xb240 BLAKE2S_MIN = 0xb241 BLAKE2S_MAX = 0xb260 MD5 = 0xd5 DBL_SHA2_256 = 0x56 MURMUR3X64_64 = 0x22 // Deprecated: use MURMUR3X64_64 MURMUR3 = MURMUR3X64_64 SHA2_256_TRUNC254_PADDED = 0x1012 X11 = 0x1100 POSEIDON_BLS12_381_A1_FC1 = 0xb401 ) func init() { // Add blake2b (64 codes) for c := uint64(BLAKE2B_MIN); c <= BLAKE2B_MAX; c++ { n := c - BLAKE2B_MIN + 1 name := fmt.Sprintf("blake2b-%d", n*8) Names[name] = c Codes[c] = name } // Add blake2s (32 codes) for c := uint64(BLAKE2S_MIN); c <= BLAKE2S_MAX; c++ { n := c - BLAKE2S_MIN + 1 name := fmt.Sprintf("blake2s-%d", n*8) Names[name] = c Codes[c] = name } } // Names maps the name of a hash to the code var Names = map[string]uint64{ "identity": IDENTITY, "sha1": SHA1, "sha2-256": SHA2_256, "sha2-512": SHA2_512, "sha3": SHA3_512, "sha3-224": SHA3_224, "sha3-256": SHA3_256, "sha3-384": SHA3_384, "sha3-512": SHA3_512, "dbl-sha2-256": DBL_SHA2_256, "murmur3-x64-64": MURMUR3X64_64, "keccak-224": KECCAK_224, "keccak-256": KECCAK_256, "keccak-384": KECCAK_384, "keccak-512": KECCAK_512, "blake3": BLAKE3, "shake-128": SHAKE_128, "shake-256": SHAKE_256, "sha2-256-trunc254-padded": SHA2_256_TRUNC254_PADDED, "x11": X11, "md5": MD5, "poseidon-bls12_381-a2-fc1": POSEIDON_BLS12_381_A1_FC1, } // Codes maps a hash code to it's name var Codes = map[uint64]string{ IDENTITY: "identity", SHA1: "sha1", SHA2_256: "sha2-256", SHA2_512: "sha2-512", SHA3_224: "sha3-224", SHA3_256: "sha3-256", SHA3_384: "sha3-384", SHA3_512: "sha3-512", DBL_SHA2_256: "dbl-sha2-256", MURMUR3X64_64: "murmur3-x64-64", KECCAK_224: "keccak-224", KECCAK_256: "keccak-256", KECCAK_384: "keccak-384", KECCAK_512: "keccak-512", BLAKE3: "blake3", SHAKE_128: "shake-128", SHAKE_256: "shake-256", SHA2_256_TRUNC254_PADDED: "sha2-256-trunc254-padded", X11: "x11", POSEIDON_BLS12_381_A1_FC1: "poseidon-bls12_381-a2-fc1", MD5: "md5", } // reads a varint from buf and returns bytes read. func uvarint(buf []byte) (uint64, []byte, error) { n, c, err := varint.FromUvarint(buf) if err != nil { return n, buf, err } if c == 0 { return n, buf, ErrVarintBufferShort } else if c < 0 { return n, buf[-c:], ErrVarintTooLong } else { return n, buf[c:], nil } } // DecodedMultihash represents a parsed multihash and allows // easy access to the different parts of a multihash. type DecodedMultihash struct { Code uint64 Name string Length int // Length is just int as it is type of len() opearator Digest []byte // Digest holds the raw multihash bytes } // Multihash is byte slice with the following form: // . // See the spec for more information. type Multihash []byte // HexString returns the hex-encoded representation of a multihash. func (m Multihash) HexString() string { return hex.EncodeToString([]byte(m)) } // String is an alias to HexString(). func (m Multihash) String() string { return m.HexString() } // FromHexString parses a hex-encoded multihash. func FromHexString(s string) (Multihash, error) { b, err := hex.DecodeString(s) if err != nil { return Multihash{}, err } return Cast(b) } // B58String returns the B58-encoded representation of a multihash. func (m Multihash) B58String() string { return b58.Encode([]byte(m)) } // FromB58String parses a B58-encoded multihash. func FromB58String(s string) (m Multihash, err error) { b, err := b58.Decode(s) if err != nil { return Multihash{}, ErrInvalidMultihash } return Cast(b) } // Cast casts a buffer onto a multihash, and returns an error // if it does not work. func Cast(buf []byte) (Multihash, error) { _, err := Decode(buf) if err != nil { return Multihash{}, err } return Multihash(buf), nil } // Decode parses multihash bytes into a DecodedMultihash. func Decode(buf []byte) (*DecodedMultihash, error) { // outline decode allowing the &dm expression to be inlined into the caller. // This moves the heap allocation into the caller and if the caller doesn't // leak dm the compiler will use a stack allocation instead. // If you do not outline this &dm always heap allocate since the pointer is // returned which cause a heap allocation because Decode's stack frame is // about to disapear. dm, err := decode(buf) if err != nil { return nil, err } return &dm, nil } func decode(buf []byte) (dm DecodedMultihash, err error) { rlen, code, hdig, err := readMultihashFromBuf(buf) if err != nil { return DecodedMultihash{}, err } dm = DecodedMultihash{ Code: code, Name: Codes[code], Length: len(hdig), Digest: hdig, } if len(buf) != rlen { return dm, ErrInconsistentLen{dm, rlen} } return dm, nil } // Encode a hash digest along with the specified function code. // Note: the length is derived from the length of the digest itself. // // The error return is legacy; it is always nil. func Encode(buf []byte, code uint64) ([]byte, error) { // FUTURE: this function always causes heap allocs... but when used, this value is almost always going to be appended to another buffer (either as part of CID creation, or etc) -- should this whole function be rethought and alternatives offered? newBuf := make([]byte, varint.UvarintSize(code)+varint.UvarintSize(uint64(len(buf)))+len(buf)) n := varint.PutUvarint(newBuf, code) n += varint.PutUvarint(newBuf[n:], uint64(len(buf))) copy(newBuf[n:], buf) return newBuf, nil } // EncodeName is like Encode() but providing a string name // instead of a numeric code. See Names for allowed values. func EncodeName(buf []byte, name string) ([]byte, error) { return Encode(buf, Names[name]) } // readMultihashFromBuf reads a multihash from the given buffer, returning the // individual pieces of the multihash. // Note: the returned digest is a slice over the passed in data and should be // copied if the buffer will be reused func readMultihashFromBuf(buf []byte) (int, uint64, []byte, error) { initBufLength := len(buf) if initBufLength < 2 { return 0, 0, nil, ErrTooShort } var err error var code, length uint64 code, buf, err = uvarint(buf) if err != nil { return 0, 0, nil, err } length, buf, err = uvarint(buf) if err != nil { return 0, 0, nil, err } if length > math.MaxInt32 { return 0, 0, nil, errors.New("digest too long, supporting only <= 2^31-1") } if int(length) > len(buf) { return 0, 0, nil, errors.New("length greater than remaining number of bytes in buffer") } // rlen is the advertised size of the CID rlen := (initBufLength - len(buf)) + int(length) return rlen, code, buf[:length], nil } // MHFromBytes reads a multihash from the given byte buffer, returning the // number of bytes read as well as the multihash func MHFromBytes(buf []byte) (int, Multihash, error) { nr, _, _, err := readMultihashFromBuf(buf) if err != nil { return 0, nil, err } return nr, Multihash(buf[:nr]), nil } go-multihash-0.2.3/multihash/000077500000000000000000000000001444154673100161245ustar00rootroot00000000000000go-multihash-0.2.3/multihash/.gitignore000066400000000000000000000000121444154673100201050ustar00rootroot00000000000000multihash go-multihash-0.2.3/multihash/.gobuilder.yml000066400000000000000000000000751444154673100207030ustar00rootroot00000000000000--- artifacts: - LICENSE - README.md - install.dist.sh go-multihash-0.2.3/multihash/LICENSE000066400000000000000000000020731444154673100171330ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2014 Juan Batiz-Benet Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. go-multihash-0.2.3/multihash/README.md000066400000000000000000000065561444154673100174170ustar00rootroot00000000000000# multihash tool The `multihash` tool uses `go-multihash` to hash things much like `shasum`. Warning: this is a **multihash** tool! Its digests follow the [multihash](https://github.com/multiformats/multihash) format. ### Install - From Source: ``` go get github.com/multiformats/go-multihash/multihash ``` - Precompiled Binaries: https://gobuilder.me/github.com/multiformats/go-multihash/multihash ### Usage ```sh > multihash -h usage: ./multihash [options] [FILE] Print or check multihash checksums. With no FILE, or when FILE is -, read standard input. Options: -a="sha2-256": one of: sha1, sha2-256, sha2-512, sha3 (shorthand) -algorithm="sha2-256": one of: sha1, sha2-256, sha2-512, sha3 -c="": check checksum matches (shorthand) -check="": check checksum matches -e="base58": one of: raw, hex, base58, base64 (shorthand) -encoding="base58": one of: raw, hex, base58, base64 -l=-1: checksums length in bits (truncate). -1 is default (shorthand) -length=-1: checksums length in bits (truncate). -1 is default ``` ### Examples #### Input ```sh # from stdin > multihash < main.go QmRZxt2b1FVZPNqd8hsiykDL3TdBDeTSPX9Kv46HmX4Gx8 # from file > ./multihash main.go QmRZxt2b1FVZPNqd8hsiykDL3TdBDeTSPX9Kv46HmX4Gx8 # from stdin "filename" > multihash - < main.go QmRZxt2b1FVZPNqd8hsiykDL3TdBDeTSPX9Kv46HmX4Gx8 ``` #### Algorithms ```sh > multihash -a ? error: algorithm '?' not one of: sha1, sha2-256, sha2-512, sha3 > multihash -a sha1 < main.go 5drkbcqJUo6fZVvcZJeVEVWAgndvLm > multihash -a sha2-256 < main.go QmcK3s36goo9v2HYcfTrDKKwxaxmJJ59etodQQFYsL5T5N > multihash -a sha2-512 < main.go 8VuDcW4CooyPQA8Cc4eYpwjhyDJZqu5m5ZMDFzWULYsVS8d119JaGeNWsZbZ2ZG2kPtbrMx31MidokCigaD65yUPAs > multihash -a sha3 < main.go 8tWDCTfAX24DYmzNixTj2ARJkqwRG736VHx5aJppmqRjhW9QT1EuTgKUmu9Pmunzq292jzPKxb2VxSsTXmjFY1HD3B ``` #### Encodings ```sh > multihash -e raw < main.go Ϛ�����I�5 S��WG>���_��]g�����u > multihash -e hex < main.go 1220cf9aa2b8a38b9b49d135095390059a57473e97aceb5fcae25d67a8b6feb58275 > multihash -e base64 < main.go EiDPmqK4o4ubSdE1CVOQBZpXRz6XrOtfyuJdZ6i2/rWCdQ== > multihash -e base58 < main.go Qmf1QjEXDmqBm7RqHKqFGNUyhzUjnX7cmgKMrGzzPceZDQ ``` #### Digest Length ```sh # we're outputing hex (good byte alignment) to show the codes changing # notice the multihash code (first 2 chars) differs! > multihash -e hex -a sha2-256 -l 256 < main.go 1220cf9aa2b8a38b9b49d135095390059a57473e97aceb5fcae25d67a8b6feb58275 > multihash -e hex -a sha2-512 -l 256 < main.go 132047a4b6c629f5545f529b0ff461dc09119969f3593186277a1cc7a8ea3560a6f1 > multihash -e hex -a sha3 -l 256 < main.go 14206b9222a1a47939e665261bd2b5573e55e7988675223adde73c1011066ad66335 # notice the multihash length (next 2 chars) differs! > multihash -e hex -a sha2-256 -l 256 < main.go 1220cf9aa2b8a38b9b49d135095390059a57473e97aceb5fcae25d67a8b6feb58275 > multihash -e hex -a sha2-256 -l 200 < main.go 1219cf9aa2b8a38b9b49d135095390059a57473e97aceb5fcae25d ``` #### Verify Checksum ```sh > multihash -c QmRZxt2b1FVZPNqd8hsiykDL3TdBDeTSPX9Kv46HmX4Gx8 < main.go OK checksums match (-q for no output) > multihash -c QmcKaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa < main.go error: computed checksum did not match (-q for no output) # works with other arguments too > multihash -e hex -l 128 -c "12102ffc284a1e82bf51e567c75b2ae6edb9" < main.go OK checksums match (-q for no output) ``` go-multihash-0.2.3/multihash/install.dist.sh000077500000000000000000000005761444154673100211030ustar00rootroot00000000000000#!/bin/sh bin=multihash # this script is currently brain dead. # it merely tries two locations. # in the future maybe use value of $PATH. binpath=/usr/local/bin if [ -d "$binpath" ]; then mv "$bin" "$binpath/$bin" echo "installed $binpath/$bin" exit 0 fi binpath=/usr/bin if [ -d "$binpath" ]; then mv "$bin" "$binpath/$bin" echo "installed $binpath/$bin" exit 0 fi go-multihash-0.2.3/multihash/main.go000066400000000000000000000050441444154673100174020ustar00rootroot00000000000000package main import ( "flag" "fmt" "io" "os" mh "github.com/multiformats/go-multihash" mhopts "github.com/multiformats/go-multihash/opts" _ "github.com/multiformats/go-multihash/register/all" _ "github.com/multiformats/go-multihash/register/miniosha256" ) var usage = `usage: %s [options] [FILE] Print or check multihash checksums. With no FILE, or when FILE is -, read standard input. Options: ` // flags var opts *mhopts.Options var checkRaw string var checkMh mh.Multihash var quiet bool var help bool func init() { flag.Usage = func() { fmt.Fprintf(os.Stderr, usage, os.Args[0]) flag.PrintDefaults() } opts = mhopts.SetupFlags(flag.CommandLine) checkStr := "check checksum matches" flag.StringVar(&checkRaw, "check", "", checkStr) flag.StringVar(&checkRaw, "c", "", checkStr+" (shorthand)") helpStr := "display help message" flag.BoolVar(&help, "help", false, helpStr) flag.BoolVar(&help, "h", false, helpStr+" (shorthand)") quietStr := "quiet output (no newline on checksum, no error text)" flag.BoolVar(&quiet, "quiet", false, quietStr) flag.BoolVar(&quiet, "q", false, quietStr+" (shorthand)") } func parseFlags(o *mhopts.Options) error { flag.Parse() if err := o.ParseError(); err != nil { return err } if checkRaw != "" { var err error checkMh, err = mhopts.Decode(o.Encoding, checkRaw) if err != nil { return fmt.Errorf("fail to decode check '%s': %s", checkRaw, err) } } return nil } func getInput() (io.ReadCloser, error) { args := flag.Args() switch { case len(args) < 1: return os.Stdin, nil case args[0] == "-": return os.Stdin, nil default: f, err := os.Open(args[0]) if err != nil { return nil, fmt.Errorf("failed to open '%s': %s", args[0], err) } return f, nil } } func printHash(o *mhopts.Options, r io.Reader) error { h, err := o.Multihash(r) if err != nil { return err } s, err := mhopts.Encode(o.Encoding, h) if err != nil { return err } if quiet { fmt.Print(s) } else { fmt.Println(s) } return nil } func main() { checkErr := func(err error) { if err != nil { die("error: ", err) } } err := parseFlags(opts) checkErr(err) if help { flag.Usage() os.Exit(0) } inp, err := getInput() checkErr(err) if checkMh != nil { err = opts.Check(inp, checkMh) checkErr(err) if !quiet { fmt.Println("OK checksums match (-q for no output)") } } else { err = printHash(opts, inp) checkErr(err) } inp.Close() } func die(v ...interface{}) { if !quiet { fmt.Fprint(os.Stderr, v...) fmt.Fprint(os.Stderr, "\n") } // flag.Usage() os.Exit(1) } go-multihash-0.2.3/multihash_test.go000066400000000000000000000206121444154673100175130ustar00rootroot00000000000000package multihash import ( "bytes" "encoding/binary" "encoding/hex" "fmt" "strings" "testing" "github.com/multiformats/go-varint" ) // maybe silly, but makes it so changing // the table accidentally has to happen twice. var tCodes = map[uint64]string{ 0x00: "identity", 0x11: "sha1", 0x12: "sha2-256", 0x13: "sha2-512", 0x14: "sha3-512", 0x15: "sha3-384", 0x16: "sha3-256", 0x17: "sha3-224", 0x56: "dbl-sha2-256", 0x22: "murmur3-x64-64", 0x1A: "keccak-224", 0x1B: "keccak-256", 0x1C: "keccak-384", 0x1D: "keccak-512", 0x1E: "blake3", 0x18: "shake-128", 0x19: "shake-256", 0x1100: "x11", 0xd5: "md5", 0x1012: "sha2-256-trunc254-padded", 0xb401: "poseidon-bls12_381-a2-fc1", } type TestCase struct { hex string code uint64 name string } var testCases = []TestCase{ {"2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", 0x00, "identity"}, {"", 0x00, "identity"}, {"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33", 0x11, "sha1"}, {"0beec7b5", 0x11, "sha1"}, {"2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", 0x12, "sha2-256"}, {"2c26b46b", 0x12, "sha2-256"}, {"2c26b46b68ffc68ff99b453c1d30413413", 0xb240, "blake2b-512"}, {"243ddb9e", 0x22, "murmur3-x64-64"}, {"f00ba4", 0x1b, "keccak-256"}, {"f84e95cb5fbd2038863ab27d3cdeac295ad2d4ab96ad1f4b070c0bf36078ef08", 0x18, "shake-128"}, {"1af97f7818a28edfdfce5ec66dbdc7e871813816d7d585fe1f12475ded5b6502b7723b74e2ee36f2651a10a8eaca72aa9148c3c761aaceac8f6d6cc64381ed39", 0x19, "shake-256"}, {"4bca2b137edc580fe50a88983ef860ebaca36c857b1f492839d6d7392452a63c82cbebc68e3b70a2a1480b4bb5d437a7cba6ecf9d89f9ff3ccd14cd6146ea7e7", 0x14, "sha3-512"}, {"d41d8cd98f00b204e9800998ecf8427e", 0xd5, "md5"}, {"14fcb37dc45fa9a3c492557121bd4d461c0db40e5dcfcaa98498bd238486c307", 0x1012, "sha2-256-trunc254-padded"}, {"14fcb37dc45fa9a3c492557121bd4d461c0db40e5dcfcaa98498bd238486c307", 0xb401, "poseidon-bls12_381-a2-fc1"}, {"04e0bb39f30b1a3feb89f536c93be15055482df748674b00d26e5a75777702e9", 0x1e, "blake3"}, } func (tc TestCase) Multihash() (Multihash, error) { ob, err := hex.DecodeString(tc.hex) if err != nil { return nil, err } pre := make([]byte, 2*binary.MaxVarintLen64) spot := pre n := binary.PutUvarint(spot, tc.code) spot = pre[n:] n += binary.PutUvarint(spot, uint64(len(ob))) nb := append(pre[:n], ob...) return Cast(nb) } func TestEncode(t *testing.T) { for _, tc := range testCases { ob, err := hex.DecodeString(tc.hex) if err != nil { t.Error(err) continue } pre := make([]byte, 2*binary.MaxVarintLen64) spot := pre n := binary.PutUvarint(spot, tc.code) spot = pre[n:] n += binary.PutUvarint(spot, uint64(len(ob))) nb := append(pre[:n], ob...) encC, err := Encode(ob, tc.code) if err != nil { t.Error(err) continue } if !bytes.Equal(encC, nb) { t.Error("encoded byte mismatch: ", encC, nb) t.Error(hex.Dump(nb)) } encN, err := EncodeName(ob, tc.name) if err != nil { t.Error(err) continue } if !bytes.Equal(encN, nb) { t.Error("encoded byte mismatch: ", encN, nb) } h, err := tc.Multihash() if err != nil { t.Error(err) } if !bytes.Equal(h, nb) { t.Error("Multihash func mismatch.") } } } func ExampleEncodeName() { // ignores errors for simplicity - don't do that at home. buf, _ := hex.DecodeString("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33") mhbuf, _ := EncodeName(buf, "sha1") mhhex := hex.EncodeToString(mhbuf) fmt.Printf("hex: %v\n", mhhex) // Output: // hex: 11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33 } func TestDecode(t *testing.T) { for _, tc := range testCases { ob, err := hex.DecodeString(tc.hex) if err != nil { t.Error(err) continue } pre := make([]byte, 2*binary.MaxVarintLen64) spot := pre n := binary.PutUvarint(spot, tc.code) spot = pre[n:] n += binary.PutUvarint(spot, uint64(len(ob))) nb := append(pre[:n], ob...) mustNotAllocateMore(t, 0, func() { dec, err := Decode(nb) if err != nil { t.Error(err) return } if dec.Code != tc.code { t.Error("decoded code mismatch: ", dec.Code, tc.code) } if dec.Name != tc.name { t.Error("decoded name mismatch: ", dec.Name, tc.name) } if dec.Length != len(ob) { t.Error("decoded length mismatch: ", dec.Length, len(ob)) } if !bytes.Equal(dec.Digest, ob) { t.Error("decoded byte mismatch: ", dec.Digest, ob) } }) } } func TestTable(t *testing.T) { for k, v := range tCodes { if Codes[k] != v { t.Error("Table mismatch: ", Codes[k], v) } if Names[v] != k { t.Error("Table mismatch: ", Names[v], k) } } for name, code := range Names { if tCodes[code] != name { if strings.HasPrefix(name, "blake") { // skip these continue } if name == "sha3" { // tested as "sha3-512" continue } t.Error("missing test case for: ", name) } } for code, name := range Codes { if tCodes[code] != name { if strings.HasPrefix(name, "blake") { // skip these continue } if name == "sha3" { // tested as "sha3-512" continue } t.Error("missing test case for: ", name) } } } func ExampleDecode() { // ignores errors for simplicity - don't do that at home. buf, _ := hex.DecodeString("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33") mhbuf, _ := EncodeName(buf, "sha1") o, _ := Decode(mhbuf) mhhex := hex.EncodeToString(o.Digest) fmt.Printf("obj: %v 0x%x %d %s\n", o.Name, o.Code, o.Length, mhhex) // Output: // obj: sha1 0x11 20 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33 } func TestCast(t *testing.T) { for _, tc := range testCases { ob, err := hex.DecodeString(tc.hex) if err != nil { t.Error(err) continue } pre := make([]byte, 2*binary.MaxVarintLen64) spot := pre n := binary.PutUvarint(spot, tc.code) spot = pre[n:] n += binary.PutUvarint(spot, uint64(len(ob))) nb := append(pre[:n], ob...) mustNotAllocateMore(t, 0, func() { if _, err := Cast(nb); err != nil { t.Error(err) return } }) // 1 for the error object. mustNotAllocateMore(t, 1, func() { if _, err = Cast(ob); err == nil { t.Error("cast failed to detect non-multihash") return } }) } } func TestHex(t *testing.T) { for _, tc := range testCases { ob, err := hex.DecodeString(tc.hex) if err != nil { t.Error(err) continue } pre := make([]byte, 2*binary.MaxVarintLen64) spot := pre n := binary.PutUvarint(spot, tc.code) spot = pre[n:] n += binary.PutUvarint(spot, uint64(len(ob))) nb := append(pre[:n], ob...) hs := hex.EncodeToString(nb) mh, err := FromHexString(hs) if err != nil { t.Error(err) continue } if !bytes.Equal(mh, nb) { t.Error("FromHexString failed", nb, mh) continue } if mh.HexString() != hs { t.Error("Multihash.HexString failed", hs, mh.HexString()) continue } } } func TestDecodeErrorInvalid(t *testing.T) { _, err := FromB58String("/ipfs/QmQTw94j68Dgakgtfd45bG3TZG6CAfc427UVRH4mugg4q4") if err != ErrInvalidMultihash { t.Fatalf("expected: %s, got %s\n", ErrInvalidMultihash, err) } } func TestBadVarint(t *testing.T) { _, err := Cast([]byte{129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 129, 1}) if err != varint.ErrOverflow { t.Error("expected error from varint longer than 64bits, got: ", err) } _, err = Cast([]byte{129, 128, 128}) if err != varint.ErrUnderflow { t.Error("expected error from cut-off varint, got: ", err) } _, err = Cast([]byte{129, 0}) if err != varint.ErrNotMinimal { t.Error("expected error non-minimal varint, got: ", err) } _, err = Cast([]byte{128, 0}) if err != varint.ErrNotMinimal { t.Error("expected error non-minimal varint, got: ", err) } } func BenchmarkEncode(b *testing.B) { tc := testCases[0] ob, err := hex.DecodeString(tc.hex) if err != nil { b.Error(err) return } b.ResetTimer() for i := 0; i < b.N; i++ { Encode(ob, tc.code) } } func BenchmarkDecode(b *testing.B) { tc := testCases[0] ob, err := hex.DecodeString(tc.hex) if err != nil { b.Error(err) return } pre := make([]byte, 2) pre[0] = byte(uint8(tc.code)) pre[1] = byte(uint8(len(ob))) nb := append(pre, ob...) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { Decode(nb) } } func BenchmarkCast(b *testing.B) { tc := testCases[0] ob, err := hex.DecodeString(tc.hex) if err != nil { b.Error(err) return } pre := make([]byte, 2) pre[0] = byte(uint8(tc.code)) pre[1] = byte(uint8(len(ob))) nb := append(pre, ob...) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { Cast(nb) } } go-multihash-0.2.3/opts/000077500000000000000000000000001444154673100151135ustar00rootroot00000000000000go-multihash-0.2.3/opts/README.md000066400000000000000000000005721444154673100163760ustar00rootroot00000000000000# mhopts - multihash options for writing commands `mhopts` is a small package that helps to write commands which may take multihash options. Check it out in action: - [multihash](../multihash) - [hashpipe](https://github.com/jbenet/go-hashpipe) Godoc: [https://godoc.org/github.com/multiformats/go-multihash/opts](https://godoc.org/github.com/multiformats/go-multihash/opts) go-multihash-0.2.3/opts/coding.go000066400000000000000000000015651444154673100167140ustar00rootroot00000000000000package opts import ( "encoding/base64" "encoding/hex" "fmt" base58 "github.com/mr-tron/base58/base58" mh "github.com/multiformats/go-multihash" ) func Decode(encoding, digest string) (mh.Multihash, error) { switch encoding { case "raw": return mh.Cast([]byte(digest)) case "hex": return hex.DecodeString(digest) case "base58": return base58.Decode(digest) case "base64": return base64.StdEncoding.DecodeString(digest) default: return nil, fmt.Errorf("unknown encoding: %s", encoding) } } func Encode(encoding string, hash mh.Multihash) (string, error) { switch encoding { case "raw": return string(hash), nil case "hex": return hex.EncodeToString(hash), nil case "base58": return base58.Encode(hash), nil case "base64": return base64.StdEncoding.EncodeToString(hash), nil default: return "", fmt.Errorf("unknown encoding: %s", encoding) } } go-multihash-0.2.3/opts/opts.go000066400000000000000000000070511444154673100164320ustar00rootroot00000000000000// Package opts helps to write commands which may take multihash // options. package opts import ( "bytes" "errors" "flag" "fmt" "io" "sort" "strings" mh "github.com/multiformats/go-multihash" ) // package errors var ( ErrMatch = errors.New("multihash checksums did not match") ) // Options is a struct used to parse cli flags. type Options struct { Encoding string Algorithm string AlgorithmCode uint64 Length int fs *flag.FlagSet } // FlagValues are the values the various option flags can take. var FlagValues = struct { Encodings []string Algorithms []string }{ Encodings: []string{"raw", "hex", "base58", "base64"}, Algorithms: func() []string { names := make([]string, 0, len(mh.Names)) for n := range mh.Names { // There are too many of these for now. // We can figure something better out later. if strings.HasPrefix(n, "blake2") { switch n { case "blake2s-256": case "blake2b-128": case "blake2b-224": case "blake2b-256": case "blake2b-384": case "blake2b-512": default: continue } } names = append(names, n) } sort.Strings(names) return names }(), } // SetupFlags adds multihash related options to given flagset. func SetupFlags(f *flag.FlagSet) *Options { // TODO: add arg for adding opt prefix and/or overriding opts o := new(Options) algoStr := "one of: " + strings.Join(FlagValues.Algorithms, ", ") f.StringVar(&o.Algorithm, "algorithm", "sha2-256", algoStr) f.StringVar(&o.Algorithm, "a", "sha2-256", algoStr+" (shorthand)") encStr := "one of: " + strings.Join(FlagValues.Encodings, ", ") f.StringVar(&o.Encoding, "encoding", "base58", encStr) f.StringVar(&o.Encoding, "e", "base58", encStr+" (shorthand)") lengthStr := "checksums length in bits (truncate). -1 is default" f.IntVar(&o.Length, "length", -1, lengthStr) f.IntVar(&o.Length, "l", -1, lengthStr+" (shorthand)") return o } // Parse parses the values of flags from given argument slice. // It is equivalent to flags.Parse(args) func (o *Options) Parse(args []string) error { if err := o.fs.Parse(args); err != nil { return err } return o.ParseError() } // ParseError checks the parsed options for errors. func (o *Options) ParseError() error { if !strIn(o.Encoding, FlagValues.Encodings) { return fmt.Errorf("encoding '%s' not %s", o.Encoding, FlagValues.Encodings) } if !strIn(o.Algorithm, FlagValues.Algorithms) { return fmt.Errorf("algorithm '%s' not %s", o.Algorithm, FlagValues.Algorithms) } var found bool o.AlgorithmCode, found = mh.Names[o.Algorithm] if !found { return fmt.Errorf("algorithm '%s' not found (lib error, pls report)", o.Algorithm) } if o.Length >= 0 { if o.Length%8 != 0 { return fmt.Errorf("length must be multiple of 8") } o.Length = o.Length / 8 h, _ := mh.GetHasher(o.AlgorithmCode) hsize := 0 if h != nil { hsize = h.Size() } if o.Length > hsize { o.Length = hsize } } return nil } // strIn checks wither string a is in set. func strIn(a string, set []string) bool { for _, s := range set { if s == a { return true } } return false } // Check reads all the data in r, calculates its multihash, // and checks it matches h1 func (o *Options) Check(r io.Reader, h1 mh.Multihash) error { h2, err := o.Multihash(r) if err != nil { return err } if !bytes.Equal(h1, h2) { return fmt.Errorf("computed checksum did not match") } return nil } // Multihash reads all the data in r and calculates its multihash. func (o *Options) Multihash(r io.Reader) (mh.Multihash, error) { return mh.SumStream(r, o.AlgorithmCode, o.Length) } go-multihash-0.2.3/register/000077500000000000000000000000001444154673100157525ustar00rootroot00000000000000go-multihash-0.2.3/register/all/000077500000000000000000000000001444154673100165225ustar00rootroot00000000000000go-multihash-0.2.3/register/all/multihash_all.go000066400000000000000000000015671444154673100217100ustar00rootroot00000000000000/* This package has no purpose except to perform registration of mulithashes. It is meant to be used as a side-effecting import, e.g. import ( _ "github.com/multiformats/go-multihash/register/all" ) This package registers many multihashes at once. Importing it will increase the size of your dependency tree significantly. It's recommended that you import this package if you're building some kind of data broker application, which may need to handle many different kinds of hashes; if you're building an application which you know only handles a specific hash, importing this package may bloat your builds unnecessarily. */ package all import ( _ "github.com/multiformats/go-multihash/register/blake2" _ "github.com/multiformats/go-multihash/register/blake3" _ "github.com/multiformats/go-multihash/register/murmur3" _ "github.com/multiformats/go-multihash/register/sha3" ) go-multihash-0.2.3/register/blake2/000077500000000000000000000000001444154673100171125ustar00rootroot00000000000000go-multihash-0.2.3/register/blake2/blake2_test.go000066400000000000000000000303341444154673100216430ustar00rootroot00000000000000package blake2 import ( "bytes" "encoding/hex" "fmt" "testing" multihash "github.com/multiformats/go-multihash/core" ) func mustHexDecode(s string) []byte { d, err := hex.DecodeString(s) if err != nil { panic(err) } return d } func TestBlake2(t *testing.T) { data := mustHexDecode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f5051525354555657") for _, tc := range [...]struct { expectedResultData []byte expectedResultNoData []byte }{ {mustHexDecode("57"), mustHexDecode("2e")}, {mustHexDecode("390e"), mustHexDecode("b1fe")}, {mustHexDecode("fe728b"), mustHexDecode("cec7ea")}, {mustHexDecode("4fe6f30f"), mustHexDecode("1271cf25")}, {mustHexDecode("cbc7880525"), mustHexDecode("7d64c5272e")}, {mustHexDecode("edb9d5a35476"), mustHexDecode("ddd9c40767f9")}, {mustHexDecode("b81be0e95423db"), mustHexDecode("4e9b03474eda9a")}, {mustHexDecode("fa9ad8e1f5618c30"), mustHexDecode("e4a6a0577479b2b4")}, {mustHexDecode("633306b8fb4c7a8345"), mustHexDecode("d6bd6fc9a3324e5f32")}, {mustHexDecode("2ffc171771c4b8b9b16d"), mustHexDecode("6fa1d8fcfd719046d762")}, {mustHexDecode("9c082c2e1484e9ec959173"), mustHexDecode("eb6ec15daf9546254f0809")}, {mustHexDecode("b6dac9c8fd27fd6079778349"), mustHexDecode("b8e1dda3ac0aa3820ad2990b")}, {mustHexDecode("2c9fce7a5b07fc61c9adce6d00"), mustHexDecode("50b4dc6f148a3f25b974e5c829")}, {mustHexDecode("fbc109122fe2fa7eeafa36d6ca77"), mustHexDecode("4b1f3c22056a5cf9a3300407d264")}, {mustHexDecode("0f69b659f66b22fbf4e34992d74c67"), mustHexDecode("b7db87196c483405e40f8401fa1fc9")}, {mustHexDecode("907d743b004a882fc18d23df3ac0a5bb"), mustHexDecode("cae66941d9efbd404e4d88758ea67670")}, {mustHexDecode("dabb9c4ad42c46bf780306fcd4d053d373"), mustHexDecode("246c0442cd564aced8145b8b60f1370aa7")}, {mustHexDecode("d7c79aaa168ec2c806756822486a3b31786c"), mustHexDecode("91a1a481a82eb3f3e6262de11f142d234945")}, {mustHexDecode("0cec62c268f2b747b050f29e8a4713c4dde635"), mustHexDecode("35bd4214446fda5ce2e05015f1ba43e26f1b96")}, {mustHexDecode("c5b9110bfb2da0ce0a55ba3f2be0aaab233c5a14"), mustHexDecode("3345524abf6bbe1809449224b5972c41790b6cf2")}, {mustHexDecode("9eb92b042d3c1f2a03441c0bafe53d93991c1466bf"), mustHexDecode("077d8272052a6edfff4047461c3a2b3d9d330dbbf0")}, {mustHexDecode("7043e1b53d58f38a1262382a0f3b8c13289752bba647"), mustHexDecode("1065c75a5ab372acff0b521808a4766c70b12b10ad8c")}, {mustHexDecode("9c9f549599752e7f4227c84f77d2156d373d57a7b31cd4"), mustHexDecode("e30b37bb45ad2f1954a0ab31666f909df8d4eabd6933e9")}, {mustHexDecode("bbdd0013817106ca72be7f23665acc5d8ac5e7cbe9b8316d"), mustHexDecode("ab3b5331a7135ed50d0f182d026e60abdb3646fd51bcf8a3")}, {mustHexDecode("0f928ecf8557ddd62b0f5fe9252632c7dd7e88e6f4faf5edf2"), mustHexDecode("94165bbe7a8a0f49fad8c1b39c40b7dd613409378dcc47681f")}, {mustHexDecode("93189ce79eb1257ecfc01a6d2d0fa345beaa34610af9ee9c1240"), mustHexDecode("7895f50fee886d460f321601da8d2db483a08c0264cd8ff3617e")}, {mustHexDecode("a6ff723c4e43a3b46655152918422485bdf8327637cf1078476d10"), mustHexDecode("b41793f77a58236ee36d36570bcd14cf00ba6a443c6c5bd4bb9eaf")}, {mustHexDecode("2e30811d4d0942f5e2bd6f52961efe6f0e583ba39ddd368e004200ab"), mustHexDecode("836cc68931c2e4e3e838602eca1902591d216837bafddfe6f0c8cb07")}, {mustHexDecode("ed641f9462d220d0aebd649fcdf0af533e4cd5a9762645c226e56e4659"), mustHexDecode("a10eae68c06d70c597699d656d6ae213430569f9c62e04cd2fc3a0c1bf")}, {mustHexDecode("e027addc1bdf2d24f8f763a22906ac457d199f8c3c3f91c20cfad7e20e55"), mustHexDecode("a5d6d5975d09c76462b3f9c74f9568d9f9fd46dfbdcbf3f14bc835298b22")}, {mustHexDecode("5640281fd6fd8302a7773814289f5170790df63f263d9a8c6c642c8c705514"), mustHexDecode("b4d7d8f500d546e71fe03f080b6bfefd567a0aa97e84bdb2cf8b15d1867c00")}, {mustHexDecode("fd9664ecb814785c8474188706e6ab0952925f9b9d8e351665ced12e84d92fad"), mustHexDecode("0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8")}, {mustHexDecode("972b75e4a5747c695af8c430e685d2090c766a067ac629f5d75ccaa532de6aab24"), mustHexDecode("ddca500c4d28f7f2816de1574f840e4878c1c5aa30c149745e0149273b214c359d")}, {mustHexDecode("6abf92bc9a9747942157afb97af768b798c1c2dd54188db396c529e6af07fcbba5bd"), mustHexDecode("90933ab63c7665e2bd6431e496ec60d38839fbec78e33aae2c152c073f64264bdab9")}, {mustHexDecode("2b5c40e57ec34bc2d1a5759e46870d7324fdc0f55208492b31d637dc42e2de8a26ce18"), mustHexDecode("148833bb2bfcc18b9e90024eaeecc0a96027a777761e0b9c93d6642937bb4b8705e218")}, {mustHexDecode("db0c682edad98e563aa47646050d812f0c0e72c21e52eb4f089cdc48fe8e0c649ec403f5"), mustHexDecode("92f3592c601fe36aa32c62e305f965905a2982dee6a45c09011ddf05f9cf9b7b5609414f")}, {mustHexDecode("0f78215590aff9081907909e4fb3ed7ee0aff65415006aa1ff5d45b670a05b1cba03afaba6"), mustHexDecode("6d82c523a958c2b00e42701be980963438d5f40572c70d3d723c03ddebdb74575866f3adbb")}, {mustHexDecode("87eba8d23f0e7104e728b9e718e622149f76ee964dff4d752d7f1a4370e7f8d0f04d8bcd5787"), mustHexDecode("dc5abbc8c533139ba5873c9562868914e501b13aadc59c143d1bfe97cbcb5fab5b65ed488158")}, {mustHexDecode("1c4481143ad1fa3d7bba1967b74e02a6d888d948573b7aef9d0b9501513366bf4c7e642f65ce36"), mustHexDecode("61a54c550005791e4726043fbfc347bb8952e520818157aeaf0d0f877c51950e06ff3157d02a6f")}, {mustHexDecode("7c6d4ba464a293c8e51402abb64ab02c0792d4d961769fbe0dce5134e20ec28d0e48ed0204dfedb4"), mustHexDecode("2e316d2c76c9760df1e604e4ffd1aa5ac6c6ac50aaa8071f7313ea931e205da084bbae9a2019f6aa")}, {mustHexDecode("1089aa00e244d33468840ba902b93f723e969b969afe728e79485c7eccf2a9ec3105dffa625ffee3ec"), mustHexDecode("592c90e91f3187c352649476b86bba76c128433e6f3ac8c75710042f4b310e1c7aea39b0aff9b51bd3")}, {mustHexDecode("2fcd69fb4270e081a222aab14a22315a7d862798000f548082b0fe02d01e37218edd6305ccbea1a35626"), mustHexDecode("f564703984efb278dfb04536d0bf4b86a17e8a9847104f773b81835ffc60b343a364e224e36552728dd6")}, {mustHexDecode("6a5c37e5490fa3988894104ce266c951aca5002cd27f4ab8aa31eed60d66ee9fbb016d71fff79d4290fd24"), mustHexDecode("5112353efd2617941caf7de611f152ac7b6fbacfb682aa43ecb707c8977ae8f307e50da1942c6eed777082")}, {mustHexDecode("2cdbbad7908e4cd48251aff565dd0cc5a17deb061c10343b2f539b44978982d3b9e7289cb167aebf48c53496"), mustHexDecode("b2e01f2639b7e74abab0bb7e88f7ab7ae94ba6292c3a42537ca288635259a50edd9c7d7a1c7b8d2e2f86848e")}, {mustHexDecode("590a0f21f0f6019bdfb1e53b76caacc8131ed402433ba425b74aacfd9858ac9fe6df644b293509392ef305d7ee"), mustHexDecode("fa9d9e37d6fe09eb8116510fadb9c61cc59e332d46cc4a365e72edc733188f08be9c0894b6dbb06023ff312506")}, {mustHexDecode("043211ff429d42bf06722329f2e71bbf3bc9fa6f7742b8bcc6e23cc0b77c708ed83772197fbe272c0323ced6d5bd"), mustHexDecode("d47deb78c6d8db06e3b38d8faa368d22cbab03cbfb2b3ad201be5729ab454278007f76dcdb14de4eb38958745f77")}, {mustHexDecode("13f0a7e600fdbd814b5d3c7a19a3128ed460e23d71a66b2875eaa6bbefca778fd5b8258ac9d5f3cbe268a88798eec7"), mustHexDecode("e4ac268b5be19d515b8ddd90bc7e89100f875fa994517409907cb6f3c6eefacc3890c84dd3e91cd2886eb57033c749")}, {mustHexDecode("5389909a11359d68263875199b2d53bc2c473d44bd5eccc562634ddaed80c6075a35bda179aa3129eaec1a11b87af6a8"), mustHexDecode("b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100")}, {mustHexDecode("d4815007ab460e95a75e2f4912b8b6bcaeefb18e81b473a58663a85da25e680cb22d965b2dacb7cd69b294b77c3a85c74c"), mustHexDecode("a993b7c6dbd66f7a45487707d7e3eda19201f7fec9dcf1ae3c0a66eb4be4d21ed8af10490cef0c3168e9ff0dcfb5dcd651")}, {mustHexDecode("b0828379fa986f452816cf9e98cbd3b7b66e7130512db924c123c465898761e8ae390b94727a782834df4f77ada7d49f9508"), mustHexDecode("3189e5764c09a2f5d1d9f5cb1967ebd3dfeade9c62af8bb0dc032bb3e90dd1e760fbaba8956f97c7602d0a2ec162169ef219")}, {mustHexDecode("c09732d4ab7631a57e3a7b94fd50bb281318b4a7eb8903b7179caec2e7d0a8bc507ccb0f14593c69318ccf2d39bc3073e564cd"), mustHexDecode("31635ed8064b99e056ed7009905673c986944a718c6e5935e7eeb67652550d56fe7ec110a383ef94ef7977be456a44503434ad")}, {mustHexDecode("22951e6c2fadbb2e9f3615895913a8e5a034d1e5dbfb7c168c2a89121be56e6ee94243b94e672452050bae6e3b53177398e0fac2"), mustHexDecode("f4e2de2be49787b13e0b38c0d02578b78a76f6c8fc48948c00f67812bd6c9ceaff17b04617532862be3cb251524b93d83a266e35")}, {mustHexDecode("35ab960da50b0d2bc0ff05a59a10fcfd58b1484c87251f872dea2a9957304e9cea84b7ec07e9eb2f716a3d16bd97693d37a79d1253"), mustHexDecode("e3af5d079bce8fbbad6f5047d77025b8e100d91ecc066fa525d290ef6a867f93b2798769067f8790df954682011617a68d7169ef15")}, {mustHexDecode("cfd083d366fab80952cfbcf2988edd1c15109870cf3296f0f9e04d4ca50610ef4dfc73a5cd28586fecc2e3e4d7c60c07b9621dcf877d"), mustHexDecode("0668149330f455fe58c70d209cff452742cc1125eee5e1d67af18e9b2a67b5ca6973940135341c2807c9237295ec0a0d173dbc28f687")}, {mustHexDecode("e2fc9688e8fa0f63dd4038157d7476df5c0a6bdba9fb95d971646f2146adf5b9e4299306c38660fec59a392d503600e62c6abf99df92ec"), mustHexDecode("89c4f154fddb635864729c086c40ff2e574ef4fa1ab592d9bee584693852cfeee57c743b9a8771443e522f454218b260838c0a913d29e5")}, {mustHexDecode("232911189422198fa470df67ba475afb61590c168e8f89744ad69e959059e168186b5344b86dd0b39f715e9ca7e922d23b0a5c29b4287962"), mustHexDecode("e7d2cb731e704ab61a3fa0ddd3bb3a6bfe3c3bc03b2c80a7545a0c9cedb575dfaa6821be9879e9ecd24350297f14470ad3d1cd2d19f27fbf")}, {mustHexDecode("e0ab326421e4732381ab2ef306d0e3751ecb537d2ec2020f87f3e15d06a263239b824d7f5921b13d03c9b383191cb5fd9f9bda879264b730a3"), mustHexDecode("a6e2604d330fa35f9f97cb89a4160928704e058f1aa0badc51b6e16afa943362fc1b32a4d79138b8103dfcad3239de59c17a267e72f7a0693e")}, {mustHexDecode("87de3953f266e1d4bddb48d0c416daeb83f1b6631c79db5886856749dc3da4e7e541ad2510c5c3332838fafe98921d6005851d22773ecff551db"), mustHexDecode("f3cc91641a39f6acada71544227505ae109b8c86c2f5fc3c4b7265c64ca6e99967824cea78f6ffb9a0851c86aa52b28ba3352164eedfefc80ddd")}, {mustHexDecode("1f01b65d74228e0ce89c98f43fb0c39868f8be8afbceb264cfc1adafebd58eae74d666fb184af4e69cac74b1c7561ab172b0ff8024a344e148e901"), mustHexDecode("cf1335ff92a6710c3cfa3dd8ac8c7a435aece775997bdaa1ac57276b0fa16b9a5f1f78a334eefafd0bc9d9cafa6633ba7abed8f67ce8d287af1822")}, {mustHexDecode("08f648dbc6b47dae03dd4b537926b02e7963679e096b2276be5200769484ddc9dd02ad8d342841dcb29916d8964ede7f09e2ecd6deb3910e5e2e36d1"), mustHexDecode("22f194f655ea58d7fefe35b09c91c91cf5e1a4047181ea7cd7674e597be65f6541fa1fdddf404e7851b1d471478048d550546d14d88345fb422c19f6")}, {mustHexDecode("dba08fdd0908deb20de12f7c54dc139457c2d6d623145ba2f6f7e01e7d3d541bed2318378eebe337ceebea5738ba52c79a454a4fa253907fc747e3b0ed"), mustHexDecode("d10c86444347b9bbb839717bc3161a10412c52fd2eb52c0a08fcd4c1f091801c0b2b09c74d716f4874761ec1b11afd66be0e13b129b6bc877720f2c7fd")}, {mustHexDecode("eafa5e0a0d3a9198276ed0d189d71424caf450dced14b223e6caa4d8d5667ecdf8268431f0b95fab70e7c0e8741107d03d3bc982a2b6765668799f0745f8"), mustHexDecode("50e5578cdbe722b76b9b7d629aec8fb4926b4073da62774e64cafa1b33627c24d70009660e784558b3daa7a65b6841976c41cf3d6891ea1ccdd10894e64d")}, {mustHexDecode("ca645dcaed18a7bd232931a5e5d20d51ebc3fd667d5c7549fe8cef2b52fb8bb83546ab55243c5c1e58a07410a89d548fea5b1221971f87448a0d594e26688c"), mustHexDecode("4ded8c5fc8b12f3273f877ca585a44ad6503249a2b345d6d9c0e67d85bcb700db4178c0303e93b8f4ad758b8e2c9fd8b3d0c28e585f1928334bb77d36782e8")}, {mustHexDecode("4665cef8ba4db4d0acb118f2987f0bb09f8f86aa445aa3d5fc9a8b346864787489e8fcecc125d17e9b56e12988eac5ecc7286883db0661b8ff05da2afff30fe4"), mustHexDecode("786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce")}, } { size := uint64(len(tc.expectedResultData)) t.Run(fmt.Sprintf("blake2b_%d", size*8), func(t *testing.T) { h, err := multihash.GetHasher(blake2b_min + size - 1) if err != nil { t.Errorf("failed to get: %s", err.Error()) return } if result := h.Sum(nil); !bytes.Equal(result, tc.expectedResultNoData) { t.Errorf("digest empty doesn't match, expected %s; got %s", hex.EncodeToString(tc.expectedResultNoData), hex.EncodeToString(result)) } n, err := h.Write(data) if err != nil { t.Errorf("hashing data failed: %s", err.Error()) return } if n != len(data) { t.Errorf("not enough bytes hashed, expected %d; got %d", len(data), n) return } if result := h.Sum(nil); !bytes.Equal(result, tc.expectedResultData) { t.Errorf("digest full doesn't match, expected %s; got %s", hex.EncodeToString(tc.expectedResultData), hex.EncodeToString(result)) } }) } } go-multihash-0.2.3/register/blake2/multihash_blake2.go000066400000000000000000000021351444154673100226600ustar00rootroot00000000000000/* This package has no purpose except to perform registration of multihashes. It is meant to be used as a side-effecting import, e.g. import ( _ "github.com/multiformats/go-multihash/register/blake2" ) This package registers several multihashes for the blake2 family (both the 's' and the 'b' variants, and in a variety of sizes). */ package blake2 import ( "hash" "golang.org/x/crypto/blake2b" "golang.org/x/crypto/blake2s" multihash "github.com/multiformats/go-multihash/core" ) const ( blake2b_min = 0xb201 blake2b_max = 0xb240 blake2s_min = 0xb241 blake2s_max = 0xb260 ) func init() { // blake2s // This package only enables support for 32byte (256 bit) blake2s. multihash.Register(blake2s_min+31, func() hash.Hash { h, err := blake2s.New256(nil) if err != nil { panic(err) } return h }) // blake2b // There's a whole range of these. for c := uint64(blake2b_min); c <= blake2b_max; c++ { size := int(c - blake2b_min + 1) multihash.Register(c, func() hash.Hash { hasher, err := blake2b.New(size, nil) if err != nil { panic(err) } return hasher }) } } go-multihash-0.2.3/register/blake3/000077500000000000000000000000001444154673100171135ustar00rootroot00000000000000go-multihash-0.2.3/register/blake3/multihash_blake3.go000066400000000000000000000011671444154673100226660ustar00rootroot00000000000000/* This package has no purpose except to register the blake3 hash function. It is meant to be used as a side-effecting import, e.g. import ( _ "github.com/multiformats/go-multihash/register/blake3" ) */ package blake3 import ( "hash" "lukechampine.com/blake3" multihash "github.com/multiformats/go-multihash/core" ) const DefaultSize = 32 const MaxSize = 128 func init() { multihash.RegisterVariableSize(multihash.BLAKE3, func(size int) (hash.Hash, bool) { if size == -1 { size = DefaultSize } else if size > MaxSize || size <= 0 { return nil, false } h := blake3.New(size, nil) return h, true }) } go-multihash-0.2.3/register/miniosha256/000077500000000000000000000000001444154673100200165ustar00rootroot00000000000000go-multihash-0.2.3/register/miniosha256/post_go1.21.go000066400000000000000000000014701444154673100223230ustar00rootroot00000000000000//go:build go1.21 // This package has no purpose except to perform registration of multihashes. // // It is meant to be used as a side-effecting import, e.g. // // import ( // _ "github.com/multiformats/go-multihash/register/miniosha256" // ) // // This package registers alternative implementations for sha2-256, using // the github.com/minio/sha256-simd library for go1.20 and bellow. Go 1.21 and // later fallback to [github.com/multiformats/go-multihash/register/sha256]. // // Deprecated: please switch to [github.com/multiformats/go-multihash/register/sha256] // as of go1.21 the go std has a SHANI implementation that is just as fast. See https://go.dev/issue/50543. // This will be removed shortly after go1.22 is released. package miniosha256 import ( _ "github.com/multiformats/go-multihash/register/sha256" ) go-multihash-0.2.3/register/miniosha256/pre_go1_21.go000066400000000000000000000017271444154673100222120ustar00rootroot00000000000000//go:build !go1.21 // This package has no purpose except to perform registration of multihashes. // // It is meant to be used as a side-effecting import, e.g. // // import ( // _ "github.com/multiformats/go-multihash/register/miniosha256" // ) // // This package registers alternative implementations for sha2-256, using // the github.com/minio/sha256-simd library for go1.20 and bellow. Go 1.21 and // later fallback to [github.com/multiformats/go-multihash/register/sha256]. // // Note if you are using go1.21 or above this package is deprecated in favor of // [github.com/multiformats/go-multihash/register/sha256] because as of go1.21 // the go std has a SHANI implementation that is just as fast. See https://go.dev/issue/50543. // This will be removed shortly after go1.22 is released. package miniosha256 import ( "github.com/minio/sha256-simd" multihash "github.com/multiformats/go-multihash/core" ) func init() { multihash.Register(multihash.SHA2_256, sha256.New) } go-multihash-0.2.3/register/murmur3/000077500000000000000000000000001444154673100173645ustar00rootroot00000000000000go-multihash-0.2.3/register/murmur3/multihash_murmur3.go000066400000000000000000000014701444154673100234050ustar00rootroot00000000000000/* This package has no purpose except to perform registration of multihashes. It is meant to be used as a side-effecting import, e.g. import ( _ "github.com/multiformats/go-multihash/register/murmur3" ) This package registers multihashes for murmur3 */ package murmur3 import ( "hash" multihash "github.com/multiformats/go-multihash/core" "github.com/spaolacci/murmur3" ) func init() { multihash.Register(multihash.MURMUR3X64_64, func() hash.Hash { return murmur64{murmur3.New64()} }) } // A wrapper is needed to export the correct size, because murmur3 incorrectly advertises Hash64 as a 128bit hash. type murmur64 struct { hash.Hash64 } func (murmur64) BlockSize() int { return 1 } func (x murmur64) Size() int { return 8 } func (x murmur64) Sum(digest []byte) []byte { return x.Hash64.Sum(digest) } go-multihash-0.2.3/register/sha256/000077500000000000000000000000001444154673100167625ustar00rootroot00000000000000go-multihash-0.2.3/register/sha256/sha256.go000066400000000000000000000007771444154673100203340ustar00rootroot00000000000000// This package has no purpose except to perform registration of multihashes. // // It is meant to be used as a side-effecting import, e.g. // // import ( // _ "github.com/multiformats/go-multihash/register/sha256" // ) // // This package an implementation of sha256 using the go std, this is recomanded // if you are using go1.21 or above. package sha256 import ( "crypto/sha256" multihash "github.com/multiformats/go-multihash/core" ) func init() { multihash.Register(multihash.SHA2_256, sha256.New) } go-multihash-0.2.3/register/sha3/000077500000000000000000000000001444154673100166105ustar00rootroot00000000000000go-multihash-0.2.3/register/sha3/multihash_sha3.go000066400000000000000000000047471444154673100220670ustar00rootroot00000000000000/* This package has no purpose except to perform registration of multihashes. It is meant to be used as a side-effecting import, e.g. import ( _ "github.com/multiformats/go-multihash/register/sha3" ) This package registers several multihashes for the sha3 family. This also includes some functions known as "shake" and "keccak", since they share much of their implementation and come in the same repos. */ package sha3 import ( "hash" "golang.org/x/crypto/sha3" multihash "github.com/multiformats/go-multihash/core" ) func init() { multihash.Register(multihash.SHA3_512, sha3.New512) multihash.Register(multihash.SHA3_384, sha3.New384) multihash.Register(multihash.SHA3_256, sha3.New256) multihash.Register(multihash.SHA3_224, sha3.New224) multihash.Register(multihash.SHAKE_128, func() hash.Hash { return shakeNormalizer{sha3.NewShake128(), 128 / 8 * 2} }) multihash.Register(multihash.SHAKE_256, func() hash.Hash { return shakeNormalizer{sha3.NewShake256(), 256 / 8 * 2} }) multihash.Register(multihash.KECCAK_256, sha3.NewLegacyKeccak256) multihash.Register(multihash.KECCAK_512, sha3.NewLegacyKeccak512) } // sha3.ShakeHash presents a somewhat odd interface, and requires a wrapper to normalize it to the usual hash.Hash interface. // // Some of the fiddly bits required by this normalization probably makes it undesirable for use in the highest performance applications; // There's at least one extra allocation in constructing it (sha3.ShakeHash is an interface, so that's one heap escape; and there's a second heap escape when this normalizer struct gets boxed into a hash.Hash interface), // and there's at least one extra allocation in getting a sum out of it (because reading a shake hash is a mutation (!) and the API only provides cloning as a way to escape this). // Fun. type shakeNormalizer struct { sha3.ShakeHash size int } func (shakeNormalizer) BlockSize() int { return 32 // Shake doesn't have a prefered block size, apparently. An arbitrary but unsurprising and positive nonzero number has been chosen to minimize the odds of fascinating bugs. } func (x shakeNormalizer) Size() int { return x.size } func (x shakeNormalizer) Sum(digest []byte) []byte { if len(digest) < x.size { digest = make([]byte, x.size) } digest = digest[0:x.size] h2 := x.Clone() // clone it, because reading mutates this kind of hash (!) which is not the standard contract for a Hash.Sum method. h2.Read(digest) // not capable of underreading. See sha3.ShakeSum256 for similar usage. return digest } go-multihash-0.2.3/registry.go000066400000000000000000000021241444154673100163240ustar00rootroot00000000000000package multihash import ( "hash" mhreg "github.com/multiformats/go-multihash/core" _ "github.com/multiformats/go-multihash/register/all" _ "github.com/multiformats/go-multihash/register/miniosha256" ) // Register is an alias for Register in the core package. // // 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) { mhreg.Register(indicator, hasherFactory) } // Register is an alias for Register in the core package. // // 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) { return mhreg.GetHasher(indicator) } // DefaultLengths maps a multihash indicator code to the output size for that hash, in units of bytes. var DefaultLengths = mhreg.DefaultLengths go-multihash-0.2.3/set.go000066400000000000000000000026711444154673100152560ustar00rootroot00000000000000package multihash // Set is a set of Multihashes, holding one copy per Multihash. type Set struct { set map[string]struct{} } // NewSet creates a new set correctly initialized. func NewSet() *Set { return &Set{ set: make(map[string]struct{}), } } // Add adds a new multihash to the set. func (s *Set) Add(m Multihash) { s.set[string(m)] = struct{}{} } // Len returns the number of elements in the set. func (s *Set) Len() int { return len(s.set) } // Has returns true if the element is in the set. func (s *Set) Has(m Multihash) bool { _, ok := s.set[string(m)] return ok } // Visit adds a multihash only if it is not in the set already. Returns true // if the multihash was added (was not in the set before). func (s *Set) Visit(m Multihash) bool { _, ok := s.set[string(m)] if !ok { s.set[string(m)] = struct{}{} return true } return false } // ForEach runs f(m) with each multihash in the set. If returns immediately if // f(m) returns an error. func (s *Set) ForEach(f func(m Multihash) error) error { for elem := range s.set { mh := Multihash(elem) if err := f(mh); err != nil { return err } } return nil } // Remove removes an element from the set. func (s *Set) Remove(m Multihash) { delete(s.set, string(m)) } // All returns a slice with all the elements in the set. func (s *Set) All() []Multihash { out := make([]Multihash, 0, len(s.set)) for m := range s.set { out = append(out, Multihash(m)) } return out } go-multihash-0.2.3/set_test.go000066400000000000000000000023651444154673100163150ustar00rootroot00000000000000package multihash import ( "crypto/rand" "errors" "testing" ) func makeRandomMultihash(t *testing.T) Multihash { t.Helper() p := make([]byte, 256) _, err := rand.Read(p) if err != nil { t.Fatal(err) } m, err := Sum(p, SHA3, 4) if err != nil { t.Fatal(err) } return m } func TestSet(t *testing.T) { mhSet := NewSet() total := 10 for i := 0; i < total; i++ { mhSet.Add(makeRandomMultihash(t)) } m0 := makeRandomMultihash(t) if mhSet.Len() != total { t.Error("bad length") } if mhSet.Has(m0) { t.Error("m0 should not be in set") } mhSet.Add(m0) if !mhSet.Has(m0) { t.Error("m0 should be in set") } i := 0 f := func(m Multihash) error { i++ if i == 3 { return errors.New("3") } return nil } mhSet.ForEach(f) if i != 3 { t.Error("forEach should have run 3 times") } mhSet.Remove(m0) if mhSet.Len() != total { t.Error("an element should have been removed") } if mhSet.Has(m0) { t.Error("m0 should not be in set") } if !mhSet.Visit(m0) { t.Error("Visit() should return true when new element added") } all := mhSet.All() if len(all) != mhSet.Len() { t.Error("All() should return all") } for _, mh := range all { if !mhSet.Has(mh) { t.Error("element in All() not in set") } } } go-multihash-0.2.3/spec/000077500000000000000000000000001444154673100150605ustar00rootroot00000000000000go-multihash-0.2.3/spec/multicodec/000077500000000000000000000000001444154673100172105ustar00rootroot00000000000000go-multihash-0.2.3/spec/multihash/000077500000000000000000000000001444154673100170565ustar00rootroot00000000000000go-multihash-0.2.3/spec_test.go000066400000000000000000000056221444154673100164530ustar00rootroot00000000000000package multihash_test import ( "encoding/csv" "fmt" "os" "strconv" "strings" "testing" "github.com/multiformats/go-multihash" _ "github.com/multiformats/go-multihash/register/all" ) func TestSpec(t *testing.T) { file, err := os.Open("spec/multicodec/table.csv") if err != nil { t.Fatal(err) } defer file.Close() reader := csv.NewReader(file) reader.LazyQuotes = false reader.FieldsPerRecord = 5 reader.TrimLeadingSpace = true values, err := reader.ReadAll() if err != nil { t.Error(err) } expectedFunctions := make(map[uint64]string, len(values)-1) if values[0][0] != "name" || values[0][1] != "tag" || values[0][2] != "code" { t.Fatal("table format has changed") } for _, v := range values[1:] { name := v[0] tag := v[1] codeStr := v[2] if tag != "multihash" { // not a multihash function continue } var code uint64 if !strings.HasPrefix(codeStr, "0x") { t.Errorf("invalid multicodec code %q (%s)", codeStr, name) continue } i, err := strconv.ParseUint(codeStr[2:], 16, 64) if err != nil { t.Errorf("invalid multibase code %q (%s)", codeStr, name) continue } code = uint64(i) expectedFunctions[code] = name } for code, name := range multihash.Codes { expectedName, ok := expectedFunctions[code] if !ok { t.Errorf("multihash %q (%x) not defined in the spec", name, code) continue } if expectedName != name { t.Errorf("encoding %q (%x) has unexpected name %q", expectedName, code, name) } } } func TestSpecVectors(t *testing.T) { file, err := os.Open("spec/multihash/tests/values/test_cases.csv") if err != nil { t.Error(err) return } defer file.Close() reader := csv.NewReader(file) reader.LazyQuotes = false reader.FieldsPerRecord = 4 reader.TrimLeadingSpace = true values, err := reader.ReadAll() if err != nil { t.Error(err) } if len(values) == 0 { t.Error("no test values") return } // check the header. if values[0][0] != "algorithm" || values[0][1] != "bits" || values[0][2] != "input" || values[0][3] != "multihash" { t.Fatal("table format has changed") } for i, testCase := range values[1:] { function := testCase[0] lengthStr := testCase[1] input := testCase[2] expectedStr := testCase[3] t.Run(fmt.Sprintf("%d/%s/%s", i, function, lengthStr), func(t *testing.T) { code, ok := multihash.Names[function] if !ok { t.Skipf("skipping %s: not supported", function) return } length, err := strconv.ParseInt(lengthStr, 10, 64) if err != nil { t.Fatalf("failed to decode length: %s", err) } if length%8 != 0 { t.Fatal("expected the length to be a multiple of 8") } actual, err := multihash.Sum([]byte(input), code, int(length/8)) if err != nil { t.Fatalf("failed to hash: %s", err) } actualStr := actual.HexString() if actualStr != expectedStr { t.Fatalf("got the wrong hash: expected %s, got %s", expectedStr, actualStr) } }) } } go-multihash-0.2.3/sum.go000066400000000000000000000043751444154673100152720ustar00rootroot00000000000000package multihash import ( "fmt" "hash" "io" mhreg "github.com/multiformats/go-multihash/core" ) // ErrSumNotSupported is returned when the Sum function code is not implemented var ErrSumNotSupported = mhreg.ErrSumNotSupported var ErrLenTooLarge = mhreg.ErrLenTooLarge // Sum obtains the cryptographic sum of a given buffer. The length parameter // indicates the length of the resulting digest. Passing a negative value uses // default length values for the selected hash function. func Sum(data []byte, code uint64, length int) (Multihash, error) { // Get the algorithm. hasher, err := mhreg.GetVariableHasher(code, length) if err != nil { return nil, err } // Feed data in. if _, err := hasher.Write(data); err != nil { return nil, err } return encodeHash(hasher, code, length) } // SumStream obtains the cryptographic sum of a given stream. The length // parameter indicates the length of the resulting digest. Passing a negative // value uses default length values for the selected hash function. func SumStream(r io.Reader, code uint64, length int) (Multihash, error) { // Get the algorithm. hasher, err := mhreg.GetVariableHasher(code, length) if err != nil { return nil, err } // Feed data in. if _, err = io.Copy(hasher, r); err != nil { return nil, err } return encodeHash(hasher, code, length) } func encodeHash(hasher hash.Hash, code uint64, length int) (Multihash, error) { // Compute final hash. // A new slice is allocated. FUTURE: see other comment below about allocation, and review together with this line to try to improve. sum := hasher.Sum(nil) // Deal with any truncation. // Unless it's an identity multihash. Those have different rules. if length < 0 { length = hasher.Size() } if len(sum) < length { return nil, ErrLenTooLarge } if length >= 0 { if code == IDENTITY { if length != len(sum) { return nil, fmt.Errorf("the length of the identity hash (%d) must be equal to the length of the data (%d)", length, len(sum)) } } sum = sum[:length] } // Put the multihash metainfo bytes at the front of the buffer. // FUTURE: try to improve allocations here. Encode does several which are probably avoidable, but it's the shape of the Encode method arguments that forces this. return Encode(sum, code) } go-multihash-0.2.3/sum_test.go000066400000000000000000000225411444154673100163240ustar00rootroot00000000000000package multihash_test import ( "bytes" "encoding/hex" "errors" "fmt" "io" "math/rand" "runtime" "sort" "testing" "github.com/multiformats/go-multihash" _ "github.com/multiformats/go-multihash/register/all" ) type SumTestCase struct { code uint64 length int input string hex string expectedSumError error } var sumTestCases = []SumTestCase{ {multihash.IDENTITY, 3, "foo", "0003666f6f", nil}, {multihash.IDENTITY, -1, "foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo", "0030666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f666f6f", nil}, {multihash.SHA1, -1, "foo", "11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33", nil}, {multihash.SHA1, 10, "foo", "110a0beec7b5ea3f0fdbc95d", nil}, {multihash.SHA2_256, -1, "foo", "12202c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", nil}, {multihash.SHA2_256, 31, "foo", "121f2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7", nil}, {multihash.SHA2_256, 32, "foo", "12202c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", nil}, {multihash.SHA2_256, 16, "foo", "12102c26b46b68ffc68ff99b453c1d304134", nil}, {multihash.SHA2_512, -1, "foo", "1340f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7", nil}, {multihash.SHA2_512, 32, "foo", "1320f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc663832", nil}, {multihash.SHA3, 32, "foo", "14204bca2b137edc580fe50a88983ef860ebaca36c857b1f492839d6d7392452a63c", nil}, {multihash.SHA3_512, 16, "foo", "14104bca2b137edc580fe50a88983ef860eb", nil}, {multihash.SHA3_512, -1, "foo", "14404bca2b137edc580fe50a88983ef860ebaca36c857b1f492839d6d7392452a63c82cbebc68e3b70a2a1480b4bb5d437a7cba6ecf9d89f9ff3ccd14cd6146ea7e7", nil}, {multihash.SHA3_224, -1, "beep boop", "171c0da73a89549018df311c0a63250e008f7be357f93ba4e582aaea32b8", nil}, {multihash.SHA3_224, 16, "beep boop", "17100da73a89549018df311c0a63250e008f", nil}, {multihash.SHA3_256, -1, "beep boop", "1620828705da60284b39de02e3599d1f39e6c1df001f5dbf63c9ec2d2c91a95a427f", nil}, {multihash.SHA3_256, 16, "beep boop", "1610828705da60284b39de02e3599d1f39e6", nil}, {multihash.SHA3_384, -1, "beep boop", "153075a9cff1bcfbe8a7025aa225dd558fb002769d4bf3b67d2aaf180459172208bea989804aefccf060b583e629e5f41e8d", nil}, {multihash.SHA3_384, 16, "beep boop", "151075a9cff1bcfbe8a7025aa225dd558fb0", nil}, {multihash.DBL_SHA2_256, 32, "foo", "5620c7ade88fc7a21498a6a5e5c385e1f68bed822b72aa63c4a9a48a02c2466ee29e", nil}, {multihash.BLAKE2B_MAX, -1, "foo", "c0e40240ca002330e69d3e6b84a46a56a6533fd79d51d97a3bb7cad6c2ff43b354185d6dc1e723fb3db4ae0737e120378424c714bb982d9dc5bbd7a0ab318240ddd18f8d", nil}, {multihash.BLAKE2B_MAX, 64, "foo", "c0e40240ca002330e69d3e6b84a46a56a6533fd79d51d97a3bb7cad6c2ff43b354185d6dc1e723fb3db4ae0737e120378424c714bb982d9dc5bbd7a0ab318240ddd18f8d", nil}, {multihash.BLAKE2B_MAX - 32, -1, "foo", "a0e40220b8fe9f7f6255a6fa08f668ab632a8d081ad87983c77cd274e48ce450f0b349fd", nil}, {multihash.BLAKE2B_MAX - 32, 32, "foo", "a0e40220b8fe9f7f6255a6fa08f668ab632a8d081ad87983c77cd274e48ce450f0b349fd", nil}, {multihash.BLAKE2B_MAX - 19, -1, "foo", "ade4022dca82ab956d5885e3f5db10cca94182f01a6ca2c47f9f4228497dcc9f4a0121c725468b852a71ec21fcbeb725df", nil}, {multihash.BLAKE2B_MAX - 19, 45, "foo", "ade4022dca82ab956d5885e3f5db10cca94182f01a6ca2c47f9f4228497dcc9f4a0121c725468b852a71ec21fcbeb725df", nil}, {multihash.BLAKE2B_MAX - 16, -1, "foo", "b0e40230e629ee880953d32c8877e479e3b4cb0a4c9d5805e2b34c675b5a5863c4ad7d64bb2a9b8257fac9d82d289b3d39eb9cc2", nil}, {multihash.BLAKE2B_MAX - 16, 48, "foo", "b0e40230e629ee880953d32c8877e479e3b4cb0a4c9d5805e2b34c675b5a5863c4ad7d64bb2a9b8257fac9d82d289b3d39eb9cc2", nil}, {multihash.BLAKE2B_MIN + 19, -1, "foo", "94e40214983ceba2afea8694cc933336b27b907f90c53a88", nil}, {multihash.BLAKE2B_MIN + 19, 20, "foo", "94e40214983ceba2afea8694cc933336b27b907f90c53a88", nil}, {multihash.BLAKE2B_MIN, -1, "foo", "81e4020152", nil}, {multihash.BLAKE2B_MIN, 1, "foo", "81e4020152", nil}, {multihash.BLAKE2S_MAX, 32, "foo", "e0e4022008d6cad88075de8f192db097573d0e829411cd91eb6ec65e8fc16c017edfdb74", nil}, {multihash.KECCAK_256, 32, "foo", "1b2041b1a0649752af1b28b3dc29a1556eee781e4a4c3a1f7f53f90fa834de098c4d", nil}, {multihash.KECCAK_512, -1, "beep boop", "1d40e161c54798f78eba3404ac5e7e12d27555b7b810e7fd0db3f25ffa0c785c438331b0fbb6156215f69edf403c642e5280f4521da9bd767296ec81f05100852e78", nil}, {multihash.SHAKE_128, 32, "foo", "1820f84e95cb5fbd2038863ab27d3cdeac295ad2d4ab96ad1f4b070c0bf36078ef08", nil}, {multihash.SHAKE_256, 64, "foo", "19401af97f7818a28edfdfce5ec66dbdc7e871813816d7d585fe1f12475ded5b6502b7723b74e2ee36f2651a10a8eaca72aa9148c3c761aaceac8f6d6cc64381ed39", nil}, {multihash.MD5, -1, "foo", "d50110acbd18db4cc2f85cedef654fccc4a4d8", nil}, {multihash.BLAKE3, 32, "foo", "1e2004e0bb39f30b1a3feb89f536c93be15055482df748674b00d26e5a75777702e9", nil}, {multihash.BLAKE3, 64, "foo", "1e4004e0bb39f30b1a3feb89f536c93be15055482df748674b00d26e5a75777702e9791074b7511b59d31c71c62f5a745689fa6c9497f68bdf1061fe07f518d410c0", nil}, {multihash.BLAKE3, 128, "foo", "1e800104e0bb39f30b1a3feb89f536c93be15055482df748674b00d26e5a75777702e9791074b7511b59d31c71c62f5a745689fa6c9497f68bdf1061fe07f518d410c0b0c27f41b3cf083f8a7fdc67a877e21790515762a754a45dcb8a356722698a7af5ed2bb608983d5aa75d4d61691ef132efe8631ce0afc15553a08fffc60ee936", nil}, {multihash.BLAKE3, -1, "foo", "1e2004e0bb39f30b1a3feb89f536c93be15055482df748674b00d26e5a75777702e9", nil}, {multihash.BLAKE3, 129, "foo", "1e810104e0bb39f30b1a3feb89f536c93be15055482df748674b00d26e5a75777702e9791074b7511b59d31c71c62f5a745689fa6c9497f68bdf1061fe07f518d410c0b0c27f41b3cf083f8a7fdc67a877e21790515762a754a45dcb8a356722698a7af5ed2bb608983d5aa75d4d61691ef132efe8631ce0afc15553a08fffc60ee9369b", multihash.ErrLenTooLarge}, } func TestSum(t *testing.T) { for _, tc := range sumTestCases { m1, err := multihash.FromHexString(tc.hex) if err != nil { t.Error(err) continue } m2, err := multihash.Sum([]byte(tc.input), tc.code, tc.length) if err != tc.expectedSumError { t.Error(tc.code, "sum failed or succeeded unexpectedly.", err) continue } else if err != nil { // test case was expected to fail at the sum, and failed as expected. stop the test. continue } if !bytes.Equal(m1, m2) { t.Error(tc.code, multihash.Codes[tc.code], "sum failed.", m1, m2) t.Error(hex.EncodeToString(m2)) } s1 := m1.HexString() if s1 != tc.hex { t.Error("hex strings not the same") } s2 := m1.B58String() m3, err := multihash.FromB58String(s2) if err != nil { t.Error("failed to decode b58") } else if !bytes.Equal(m3, m1) { t.Error("b58 failing bytes") } else if s2 != m3.B58String() { t.Error("b58 failing string") } } } func BenchmarkSum(b *testing.B) { tc := sumTestCases[0] for i := 0; i < b.N; i++ { _, _ = multihash.Sum([]byte(tc.input), tc.code, tc.length) } } func BenchmarkBlake2B(b *testing.B) { sizes := []uint64{128, 129, 130, 255, 256, 257, 386, 512} for _, s := range sizes { func(si uint64) { b.Run(fmt.Sprintf("blake2b-%d", s), func(b *testing.B) { arr := []byte("test data for some hashing, this is broken") b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { m, err := multihash.Sum(arr, multihash.BLAKE2B_MIN+si/8-1, -1) if err != nil { b.Fatal(err) } runtime.KeepAlive(m) } }) }(s) } } func TestSmallerLengthHashID(t *testing.T) { data := []byte("Identity hash input data.") dataLength := len(data) // Normal case: `length == len(data)`. _, err := multihash.Sum(data, multihash.IDENTITY, dataLength) if err != nil { t.Fatal(err) } // Unconstrained length (-1): also allowed. _, err = multihash.Sum(data, multihash.IDENTITY, -1) if err != nil { t.Fatal(err) } // Any other variation of those two scenarios should fail. for l := dataLength - 1; l >= 0; l-- { _, err = multihash.Sum(data, multihash.IDENTITY, l) if err == nil { t.Fatalf("identity hash of length %d smaller than data length %d didn't fail", l, dataLength) } } } func TestTooLargeLength(t *testing.T) { _, err := multihash.Sum([]byte("test"), multihash.SHA2_256, 33) if err != multihash.ErrLenTooLarge { t.Fatal("bad error", err) } } func TestBasicSum(t *testing.T) { for code, name := range multihash.Codes { _, err := multihash.Sum([]byte("test"), code, -1) switch { case errors.Is(err, multihash.ErrSumNotSupported): case err == nil: default: t.Errorf("unexpected error for %s: %s", name, err) } } } var Sink []byte type codeNamePair struct { id uint64 name string } func BenchmarkSumAllLarge(b *testing.B) { var data [1024 * 1024 * 16]byte src := rand.New(rand.NewSource(0x4242424242424242)) _, err := io.ReadFull(src, data[:]) if err != nil { b.Fatal(err) } // Write to a slice to sort elements s := make([]codeNamePair, 0, len(multihash.Codes)) for id, name := range multihash.Codes { s = append(s, codeNamePair{id, name}) } sort.Slice(s, func(x, y int) bool { return s[x].id < s[y].id }) for _, v := range s { h, e := multihash.GetHasher(v.id) if h == nil || e != nil { continue // Don't benchmark unsupported hashing functions } b.Run(v.name, func(b *testing.B) { b.SetBytes(int64(len(data))) for i := b.N; i > 0; i-- { var err error Sink, err = multihash.Sum(data[:], v.id, -1) if err != nil { b.Fatal(err) } } }) } } go-multihash-0.2.3/test/000077500000000000000000000000001444154673100151055ustar00rootroot00000000000000go-multihash-0.2.3/test/.gitignore000066400000000000000000000000161444154673100170720ustar00rootroot00000000000000bin/multihash go-multihash-0.2.3/test/Makefile000066400000000000000000000003201444154673100165400ustar00rootroot00000000000000all: deps deps: cd sharness && make deps clean: cd sharness && make clean test: test_expensive test_expensive: cd sharness && make TEST_EXPENSIVE=1 test_cheap: cd sharness && make .PHONY: all clean go-multihash-0.2.3/test/sharness/000077500000000000000000000000001444154673100167335ustar00rootroot00000000000000go-multihash-0.2.3/test/sharness/.gitignore000066400000000000000000000000621444154673100207210ustar00rootroot00000000000000lib/sharness/ test-results/ trash directory.*.sh/ go-multihash-0.2.3/test/sharness/Makefile000066400000000000000000000013741444154673100204000ustar00rootroot00000000000000# Run tests # # Copyright (c) 2014 Christian Couder # MIT Licensed; see the LICENSE file in this repository. # # NOTE: run with TEST_VERBOSE=1 for verbose sharness tests. T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)) BINS = bin/multihash SHARNESS = lib/sharness/sharness.sh MULTIHASH_CMD = ../../multihash MULTIHASH_ROOT = ../../ all: clean deps $(T) aggregate clean: @echo "*** $@ ***" -rm -rf test-results -rm -rf $(BINS) $(T): @echo "*** $@ ***" ./$@ aggregate: @echo "*** $@ ***" lib/test-aggregate-results.sh deps: $(SHARNESS) $(BINS) $(SHARNESS): @echo "*** installing $@ ***" lib/install-sharness.sh bin/multihash: $(MULTIHASH_ROOT)/**/*.go go build -o bin/multihash $(MULTIHASH_CMD) bins: $(BINS) .PHONY: all clean $(T) aggregate go-multihash-0.2.3/test/sharness/lib/000077500000000000000000000000001444154673100175015ustar00rootroot00000000000000go-multihash-0.2.3/test/sharness/lib/install-sharness.sh000077500000000000000000000012121444154673100233260ustar00rootroot00000000000000#!/bin/sh # install sharness.sh # # Copyright (c) 2014 Juan Batiz-Benet # MIT Licensed; see the LICENSE file in this repository. # # settings version=50229a79ba22b2f13ccd82451d86570fecbd194c urlprefix=https://github.com/mlafeldt/sharness.git clonedir=lib sharnessdir=sharness die() { echo >&2 "$@" exit 1 } mkdir -p "$clonedir" || die "Could not create '$clonedir' directory" cd "$clonedir" || die "Could not cd into '$clonedir' directory" git clone "$urlprefix" || die "Could not clone '$urlprefix'" cd "$sharnessdir" || die "Could not cd into '$sharnessdir' directory" git checkout "$version" || die "Could not checkout '$version'" exit 0 go-multihash-0.2.3/test/sharness/lib/test-aggregate-results.sh000077500000000000000000000006311444154673100244420ustar00rootroot00000000000000#!/bin/sh # # Script to aggregate results using Sharness # # Copyright (c) 2014 Christian Couder # MIT Licensed; see the LICENSE file in this repository. # SHARNESS_AGGREGATE="lib/sharness/aggregate-results.sh" test -f "$SHARNESS_AGGREGATE" || { echo >&2 "Cannot find: $SHARNESS_AGGREGATE" echo >&2 "Please check Sharness installation." exit 1 } ls test-results/t*-*.sh.*.counts | "$SHARNESS_AGGREGATE" go-multihash-0.2.3/test/sharness/lib/test-lib.sh000066400000000000000000000022061444154673100215600ustar00rootroot00000000000000# Test framework for go-ipfs # # Copyright (c) 2014 Christian Couder # MIT Licensed; see the LICENSE file in this repository. # # We are using sharness (https://github.com/mlafeldt/sharness) # which was extracted from the Git test framework. # Use the multihash tool to test against # Add current directory to path, for multihash tool. PATH=$(pwd)/bin:${PATH} # Set sharness verbosity. we set the env var directly as # it's too late to pass in --verbose, and --verbose is harder # to pass through in some cases. test "$TEST_VERBOSE" = 1 && verbose=t # assert the `multihash` we're using is the right one. if test `which multihash` != $(pwd)/bin/multihash; then echo >&2 "Cannot find the tests' local multihash tool." echo >&2 "Please check test and multihash tool installation." exit 1 fi SHARNESS_LIB="lib/sharness/sharness.sh" . "$SHARNESS_LIB" || { echo >&2 "Cannot source: $SHARNESS_LIB" echo >&2 "Please check Sharness installation." exit 1 } # Please put go-multihash specific shell functions below for hashbin in sha1sum shasum; do if type "$hashbin"; then export SHASUMBIN="$hashbin" && test_set_prereq SHASUM && break fi done go-multihash-0.2.3/test/sharness/t0010-basics.sh000077500000000000000000000007711444154673100213050ustar00rootroot00000000000000#!/bin/sh # # Copyright (c) 2015 Christian Couder # MIT Licensed; see the LICENSE file in this repository. # test_description="Basic tests" . lib/test-lib.sh test_expect_success "current dir is writable" ' echo "It works!" >test.txt ' test_expect_success "multihash is available" ' type multihash ' test_expect_success "multihash help output looks good" ' multihash -h 2>help.txt && egrep -i "^usage:" help.txt >/dev/null && egrep -i "multihash .*options.*file" help.txt >/dev/null ' test_done go-multihash-0.2.3/test/sharness/t0020-sha1.sh000077500000000000000000000012601444154673100206700ustar00rootroot00000000000000#!/bin/sh # # Copyright (c) 2015 Christian Couder # MIT Licensed; see the LICENSE file in this repository. # test_description="sha1 tests" . lib/test-lib.sh test_expect_success "setup sha1 tests" ' echo "Hash me!" >hash_me.txt && SHA1=bc6f2c3cd945bc754789e50b2f68deee2f421810 && echo "1114$SHA1" >actual ' test_expect_success "'multihash -a=sha1 -e=hex' works" ' multihash -a=sha1 -e=hex hash_me.txt >expected ' test_expect_success "'multihash -a=sha1 -e=hex' output looks good" ' test_cmp expected actual ' test_expect_success SHASUM "check hash using shasum" ' echo "$SHA1 hash_me.txt" >actual && $SHASUMBIN hash_me.txt >expected && test_cmp expected actual ' test_done go-multihash-0.2.3/test/sharness/t0030-blake3.sh000077500000000000000000000074061444154673100212060ustar00rootroot00000000000000#!/bin/sh # # Copyright (c) 2015 Christian Couder # MIT Licensed; see the LICENSE file in this repository. # test_description="blake3 tests" . lib/test-lib.sh test_expect_success "'multihash -a=blake3 -e=hex' succeeds" ' echo "Hash me!" >hash_me.txt && multihash -a=blake3 -e=hex hash_me.txt >/dev/null ' test_hasher() { INPUT_LEN=$1 EXPECTED=$2 test_expect_success "'multihash -a=blake3 -e=hex' output is correct (input len=$INPUT_LEN)" ' go run ../t0030-lib/data.go $INPUT_LEN | multihash -a=blake3 -e=hex >actual echo $EXPECTED >expected test_cmp expected actual ' } # Copied from official test vector, see: # # https://github.com/BLAKE3-team/BLAKE3/blob/080b3330159a19407dddb407dc917925ac40c4d3/test_vectors/test_vectors.json test_hasher 0 "1e20af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262" test_hasher 1 "1e202d3adedff11b61f14c886e35afa036736dcd87a74d27b5c1510225d0f592e213" test_hasher 2 "1e207b7015bb92cf0b318037702a6cdd81dee41224f734684c2c122cd6359cb1ee63" test_hasher 3 "1e20e1be4d7a8ab5560aa4199eea339849ba8e293d55ca0a81006726d184519e647f" test_hasher 4 "1e20f30f5ab28fe047904037f77b6da4fea1e27241c5d132638d8bedce9d40494f32" test_hasher 5 "1e20b40b44dfd97e7a84a996a91af8b85188c66c126940ba7aad2e7ae6b385402aa2" test_hasher 6 "1e2006c4e8ffb6872fad96f9aaca5eee1553eb62aed0ad7198cef42e87f6a616c844" test_hasher 7 "1e203f8770f387faad08faa9d8414e9f449ac68e6ff0417f673f602a646a891419fe" test_hasher 8 "1e202351207d04fc16ade43ccab08600939c7c1fa70a5c0aaca76063d04c3228eaeb" test_hasher 63 "1e20e9bc37a594daad83be9470df7f7b3798297c3d834ce80ba85d6e207627b7db7b" test_hasher 64 "1e204eed7141ea4a5cd4b788606bd23f46e212af9cacebacdc7d1f4c6dc7f2511b98" test_hasher 65 "1e20de1e5fa0be70df6d2be8fffd0e99ceaa8eb6e8c93a63f2d8d1c30ecb6b263dee" test_hasher 127 "1e20d81293fda863f008c09e92fc382a81f5a0b4a1251cba1634016a0f86a6bd640d" test_hasher 128 "1e20f17e570564b26578c33bb7f44643f539624b05df1a76c81f30acd548c44b45ef" test_hasher 129 "1e20683aaae9f3c5ba37eaaf072aed0f9e30bac0865137bae68b1fde4ca2aebdcb12" test_hasher 1023 "1e2010108970eeda3eb932baac1428c7a2163b0e924c9a9e25b35bba72b28f70bd11" test_hasher 1024 "1e2042214739f095a406f3fc83deb889744ac00df831c10daa55189b5d121c855af7" test_hasher 1025 "1e20d00278ae47eb27b34faecf67b4fe263f82d5412916c1ffd97c8cb7fb814b8444" test_hasher 2048 "1e20e776b6028c7cd22a4d0ba182a8bf62205d2ef576467e838ed6f2529b85fba24a" test_hasher 2049 "1e205f4d72f40d7a5f82b15ca2b2e44b1de3c2ef86c426c95c1af0b6879522563030" test_hasher 3072 "1e20b98cb0ff3623be03326b373de6b9095218513e64f1ee2edd2525c7ad1e5cffd2" test_hasher 3073 "1e207124b49501012f81cc7f11ca069ec9226cecb8a2c850cfe644e327d22d3e1cd3" test_hasher 4096 "1e20015094013f57a5277b59d8475c0501042c0b642e531b0a1c8f58d2163229e969" test_hasher 4097 "1e209b4052b38f1c5fc8b1f9ff7ac7b27cd242487b3d890d15c96a1c25b8aa0fb995" test_hasher 5120 "1e209cadc15fed8b5d854562b26a9536d9707cadeda9b143978f319ab34230535833" test_hasher 5121 "1e20628bd2cb2004694adaab7bbd778a25df25c47b9d4155a55f8fbd79f2fe154cff" test_hasher 6144 "1e203e2e5b74e048f3add6d21faab3f83aa44d3b2278afb83b80b3c35164ebeca205" test_hasher 6145 "1e20f1323a8631446cc50536a9f705ee5cb619424d46887f3c376c695b70e0f0507f" test_hasher 7168 "1e2061da957ec2499a95d6b8023e2b0e604ec7f6b50e80a9678b89d2628e99ada77a" test_hasher 7169 "1e20a003fc7a51754a9b3c7fae0367ab3d782dccf28855a03d435f8cfe74605e7817" test_hasher 8192 "1e20aae792484c8efe4f19e2ca7d371d8c467ffb10748d8a5a1ae579948f718a2a63" test_hasher 8193 "1e20bab6c09cb8ce8cf459261398d2e7aef35700bf488116ceb94a36d0f5f1b7bc3b" test_hasher 16384 "1e20f875d6646de28985646f34ee13be9a576fd515f76b5b0a26bb324735041ddde4" test_hasher 31744 "1e2062b6960e1a44bcc1eb1a611a8d6235b6b4b78f32e7abc4fb4c6cdcce94895c47" test_hasher 102400 "1e20bc3e3d41a1146b069abffad3c0d44860cf664390afce4d9661f7902e7943e085" test_done go-multihash-0.2.3/test/sharness/t0030-lib/000077500000000000000000000000001444154673100202455ustar00rootroot00000000000000go-multihash-0.2.3/test/sharness/t0030-lib/data.go000066400000000000000000000015221444154673100215050ustar00rootroot00000000000000// Generate hasher input that matches BLAKE3's test vectors. // // See: // // https://github.com/BLAKE3-team/BLAKE3/blob/080b3330159a19407dddb407dc917925ac40c4d3/test_vectors/test_vectors.json package main import ( "fmt" "os" "strconv" ) var usage = `usage: %s n Generate n bytes of input for blake3 test vector. ` const BYTE_LOOP = 251 func main() { if len(os.Args) != 2 { fmt.Fprintf(os.Stderr, usage, os.Args[0]) os.Exit(1) } c, err := strconv.ParseUint(os.Args[1], 0, 32) if err != nil { die(err) } var b [BYTE_LOOP]uint8 for i := range b { b[i] = uint8(i) } for c > 0 { var w uint64 = BYTE_LOOP if c < BYTE_LOOP { w = c } _, err := os.Stdout.Write(b[:w]) if err != nil { die(err) } c -= w } } func die(v ...interface{}) { fmt.Fprint(os.Stderr, v...) fmt.Fprint(os.Stderr, "\n") os.Exit(1) } go-multihash-0.2.3/version.json000066400000000000000000000000311444154673100165000ustar00rootroot00000000000000{ "version": "v0.2.3" }