diff --git a/README.md b/README.md index 67d59ad..b1beab4 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ of these in superfluous repositories of their own, I'm putting them here. Contents: + ahash/ Provides hashes from string algorithm specifiers. assert/ Error handling, assertion-style. cmd/ atping/ Automated TCP ping, meant for putting in cronjobs. @@ -32,6 +33,7 @@ Contents: readchain/ Print the common name for the certificates in a bundle. renfnv/ Rename a file to base32-encoded 64-bit FNV-1a hash. + rhash/ Compute the digest of remote files. showimp Display the external imports in a package. ski Display the SKI for PEM-encoded TLS material. stealchain/ Dump the verified chain from a TLS diff --git a/cmd/rhash/README b/cmd/rhash/README new file mode 100644 index 0000000..071f7c6 --- /dev/null +++ b/cmd/rhash/README @@ -0,0 +1,22 @@ +rhash: remote hashing tool + +Usage: rhash [-a algo] [-h] [-l set] urls... +Compute the hash over each URL. + +Flags: + -a algo Specify the hash algorithm to use; the default is sha256. + -h Print this help message. + -l set List the hash functions under set. Set can be one of all, + secure to list only cryptographic hash functions, or + insecure to list only non-cryptographic hash functions. + +Examples: + Compute the SHA256 digest of the LICENSE in this repository: + + $ rhash https://raw.githubusercontent.com/kisom/goutils/7391da8567952f69990194ead2842d21df217c89/LICENSE + LICENSE: sha256=620bfadeb698df6c6db73908689a29371a9d4cff32b08c48a5c4307946093980 + + Compute the SHA-1 digest of the LICENSE in this repository: + + $ rhash -a sha1 https://raw.githubusercontent.com/kisom/goutils/7391da8567952f69990194ead2842d21df217c89/LICENSE + LICENSE: sha1=83c6e2e410715058ed6e7c1572176122c024e367 diff --git a/cmd/rhash/main.go b/cmd/rhash/main.go new file mode 100644 index 0000000..6bf20cf --- /dev/null +++ b/cmd/rhash/main.go @@ -0,0 +1,106 @@ +package main + +import ( + "flag" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "os" + "path/filepath" + + "github.com/kisom/goutils/ahash" + "github.com/kisom/goutils/die" + "github.com/kisom/goutils/lib" +) + +func fetch(remote string) ([]byte, error) { + resp, err := http.Get(remote) + if err != nil { + return nil, err + } + + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + return body, nil +} + +func usage(w io.Writer) { + fmt.Fprintf(w, `Usage: %s [-a algo] [-h] [-l set] urls... +Compute the hash over each URL. + +Flags: + -a algo Specify the hash algorithm to use; the default is sha256. + -h Print this help message. + -l set List the hash functions under set. Set can be one of all, + secure to list only cryptographic hash functions, or + insecure to list only non-cryptographic hash functions. + +`, lib.ProgName()) +} + +func init() { + flag.Usage = func() { usage(os.Stderr) } +} + +func main() { + var algo, list string + var help bool + flag.StringVar(&algo, "a", "sha256", "hash algorithm to use") + flag.BoolVar(&help, "h", false, "print a help message") + flag.StringVar(&list, "l", "", "list known hash algorithms (one of all, secure, insecure)") + flag.Parse() + + if help { + usage(os.Stdout) + } + + if list != "" { + var hashes []string + switch list { + case "all": + hashes = ahash.HashList() + case "secure": + hashes = ahash.SecureHashList() + case "insecure": + hashes = ahash.InsecureHashList() + default: + die.With("list option must be one of all, secure, or insecure.") + } + + for _, algo := range hashes { + fmt.Printf("- %s\n", algo) + } + os.Exit(1) + } + + for _, remote := range flag.Args() { + u, err := url.Parse(remote) + if err != nil { + lib.Warn(err, "parsing %s", remote) + continue + } + + name := filepath.Base(u.Path) + if name == "" { + lib.Warnx("source URL doesn't appear to name a file") + continue + } + + body, err := fetch(remote) + if err != nil { + lib.Warn(err, "fetching %s", remote) + continue + } + + sum, err := ahash.Sum(algo, body) + if err != nil { + lib.Err(lib.ExitFailure, err, "while hashing data") + } + fmt.Printf("%s: %s=%x\n", name, algo, sum) + } +} diff --git a/cmd/rsha256/main.go b/cmd/rsha256/main.go deleted file mode 100644 index 6b447c0..0000000 --- a/cmd/rsha256/main.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "crypto/sha256" - "flag" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "path/filepath" - - "github.com/kisom/goutils/lib" -) - -func fetch(remote string) ([]byte, error) { - resp, err := http.Get(remote) - if err != nil { - return nil, err - } - - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - return body, nil -} - -func main() { - flag.Parse() - - for _, remote := range flag.Args() { - u, err := url.Parse(remote) - if err != nil { - lib.Warn(err, "parsing %s", remote) - continue - } - - name := filepath.Base(u.Path) - if name == "" { - lib.Warnx("source URL doesn't appear to name a file") - continue - } - - body, err := fetch(remote) - if err != nil { - lib.Warn(err, "fetching %s", remote) - continue - } - - h := sha256.Sum256(body) - fmt.Printf("%s: sha256=%x\n", name, h) - } -}