Add rhash for hashing remote files.

This was originally rsha256, but it's been updated to support multiple
algorithms.
This commit is contained in:
Kyle Isom 2017-11-16 08:22:46 -08:00
parent 41df73d7a8
commit fc77225740
4 changed files with 130 additions and 54 deletions

View File

@ -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

22
cmd/rhash/README Normal file
View File

@ -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

106
cmd/rhash/main.go Normal file
View File

@ -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)
}
}

View File

@ -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)
}
}