1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-07-02 03:28:25 +08:00

go-multihash update

This commit is contained in:
Juan Batiz-Benet
2015-02-07 12:53:10 -08:00
parent 757a71f2bf
commit a4c522bcd4
19 changed files with 600 additions and 2 deletions

4
Godeps/Godeps.json generated
View File

@ -176,8 +176,8 @@
},
{
"ImportPath": "github.com/jbenet/go-multihash",
"Comment": "0.1.0-19-g8ce5cb1",
"Rev": "8ce5cb1b82e1b4c1bea1fdf3cd467ef49301734e"
"Comment": "0.1.0-33-g4e09420",
"Rev": "4e09420ceb2db37a5fbb149821b9e63d88d47218"
},
{
"ImportPath": "github.com/jbenet/go-peerstream",

View File

@ -0,0 +1,11 @@
language: go
go:
- 1.3
- release
- tip
script:
- make test
env: TEST_VERBOSE=1

View File

@ -0,0 +1,11 @@
test: go_test other_tests
other_tests:
cd test && make test
go_test: go_deps
go test -race -cpu=5 -v ./...
go_deps:
go get code.google.com/p/go.crypto/sha3
go get github.com/jbenet/go-base58

View File

@ -1,5 +1,7 @@
# go-multihash
![travis](https://travis-ci.org/jbenet/go-multihash.svg)
[multihash](//github.com/jbenet/multihash) implementation in Go.
## Example

View File

@ -0,0 +1 @@
multihash

View File

@ -0,0 +1,116 @@
# 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/jbenet/multihash) format.
### Install
```
go get github.com/jbenet/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
Ϛ<><CF9A><EFBFBD><EFBFBD><EFBFBD>I<EFBFBD>5 S<><53>WG><3E><><EFBFBD>_<EFBFBD><5F>]g<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>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)
```

View File

@ -0,0 +1,40 @@
package main
import (
"encoding/base64"
"encoding/hex"
"fmt"
base58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58"
mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/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), nil
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)
}
}

View File

@ -0,0 +1,208 @@
package main
import (
"bytes"
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"strings"
mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
)
var usage = `usage: %s [options] [FILE]
Print or check multihash checksums.
With no FILE, or when FILE is -, read standard input.
Options:
`
// flags
var encodings = []string{"raw", "hex", "base58", "base64"}
var algorithms = []string{"sha1", "sha2-256", "sha2-512", "sha3"}
var encoding string
var algorithm string
var algorithmCode int
var length int
var checkRaw string
var checkMh mh.Multihash
var inputFilename string
var quiet bool
// joined names
var algoStr string
var encStr string
func init() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, usage, os.Args[0])
flag.PrintDefaults()
}
algoStr = "one of: " + strings.Join(algorithms, ", ")
flag.StringVar(&algorithm, "algorithm", "sha2-256", algoStr)
flag.StringVar(&algorithm, "a", "sha2-256", algoStr+" (shorthand)")
encStr = "one of: " + strings.Join(encodings, ", ")
flag.StringVar(&encoding, "encoding", "base58", encStr)
flag.StringVar(&encoding, "e", "base58", encStr+" (shorthand)")
checkStr := "check checksum matches"
flag.StringVar(&checkRaw, "check", "", checkStr)
flag.StringVar(&checkRaw, "c", "", checkStr+" (shorthand)")
lengthStr := "checksums length in bits (truncate). -1 is default"
flag.IntVar(&length, "length", -1, lengthStr)
flag.IntVar(&length, "l", -1, lengthStr+" (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 strIn(a string, set []string) bool {
for _, s := range set {
if s == a {
return true
}
}
return false
}
func parseFlags() error {
flag.Parse()
if !strIn(algorithm, algorithms) {
return fmt.Errorf("algorithm '%s' not %s", algorithm, algoStr)
}
var found bool
algorithmCode, found = mh.Names[algorithm]
if !found {
return fmt.Errorf("algorithm '%s' not found (lib error, pls report).")
}
if !strIn(encoding, encodings) {
return fmt.Errorf("encoding '%s' not %s", encoding, encStr)
}
if checkRaw != "" {
var err error
checkMh, err = Decode(encoding, checkRaw)
if err != nil {
return fmt.Errorf("fail to decode check '%s': %s", checkRaw, err)
}
}
if length >= 0 {
if length%8 != 0 {
return fmt.Errorf("length must be multiple of 8")
}
length = length / 8
if length > mh.DefaultLengths[algorithmCode] {
length = mh.DefaultLengths[algorithmCode]
}
}
return nil
}
func getInput() (io.ReadCloser, error) {
args := flag.Args()
switch {
case len(args) < 1:
inputFilename = "-"
return os.Stdin, nil
case args[0] == "-":
inputFilename = "-"
return os.Stdin, nil
default:
inputFilename = args[0]
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 check(h1 mh.Multihash, r io.Reader) error {
h2, err := hash(r)
if err != nil {
return err
}
if !bytes.Equal(h1, h2) {
if quiet {
os.Exit(1)
}
return fmt.Errorf("computed checksum did not match (-q for no output)")
}
if !quiet {
fmt.Println("OK checksums match (-q for no output)")
}
return nil
}
func hash(r io.Reader) (mh.Multihash, error) {
b, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
return mh.Sum(b, algorithmCode, length)
}
func printHash(r io.Reader) error {
h, err := hash(r)
if err != nil {
return err
}
s, err := Encode(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()
checkErr(err)
inp, err := getInput()
checkErr(err)
if checkMh != nil {
err = check(checkMh, inp)
checkErr(err)
} else {
err = printHash(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)
}

View File

@ -0,0 +1 @@
bin/multihash

View File

@ -0,0 +1,25 @@
BINS = bin/multihash
MULTIHASH_ROOT = ../
MULTIHASH_CMD = ../multihash
all: deps
deps: bins
clean:
rm $(BINS)
bins: $(BINS)
bin/multihash: $(MULTIHASH_ROOT)/**/*.go
go build -o bin/multihash $(MULTIHASH_CMD)
test: test_expensive
test_expensive:
cd sharness && make TEST_EXPENSIVE=1
test_cheap:
cd sharness && make
.PHONY: all clean

View File

@ -0,0 +1,3 @@
lib/sharness/
test-results/
trash directory.*.sh/

View File

@ -0,0 +1,37 @@
# 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
all: clean deps $(T) aggregate
clean:
@echo "*** $@ ***"
-rm -rf test-results
$(T):
@echo "*** $@ ***"
./$@
aggregate:
@echo "*** $@ ***"
lib/test-aggregate-results.sh
deps: $(SHARNESS) $(BINS)
$(SHARNESS):
@echo "*** installing $@ ***"
lib/install-sharness.sh
bin/%:
@echo "*** installing $@ ***"
cd .. && make $@
.PHONY: all clean $(T) aggregate

View File

@ -0,0 +1 @@
../bin

View File

@ -0,0 +1,26 @@
#!/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

View File

@ -0,0 +1,17 @@
#!/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"

View File

@ -0,0 +1,43 @@
# 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

View File

@ -0,0 +1,25 @@
#!/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" '
test_must_fail multihash -h 2>help.txt &&
cat help.txt | egrep -i "^usage:" >/dev/null &&
cat help.txt | egrep -i "multihash .*options.*file" >/dev/null
'
test_done

View File

@ -0,0 +1,31 @@
#!/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

Binary file not shown.