Hash 値を計算するパッケージを作ってみた

Windows で hash 値を計算するいい感じのツールがない1 ので,もう自分で作っちゃったよ。 といっても自前の部分は殆どないけどね。

詳しくは README.md を見ていただくとして,実際に計算をするのはこの関数。

package hash

import (
    "crypto"
    "io"
    "strings"

    "github.com/pkg/errors"
)

var (
    //ErrNoImplement is error "no implementation"
    ErrNoImplement = errors.New("no implementation")
)

//Value returns hash value string from io.Reader
func Value(r io.Reader, alg crypto.Hash) ([]byte, error) {
    if !alg.Available() {
        return nil, errors.Wrap(ErrNoImplement, "error "+algoString(alg))
    }
    h := alg.New()
    io.Copy(h, r)
    return h.Sum(nil), nil
}

呼び出し側はこんな感じ(空文字列の SHA1 値を取得する場合)。

v, err := hash.Value(bytes.NewBuffer([]byte("")), crypto.SHA1)
if err != nil {
    return
}
fmt.Printf("%x\n", v)
// Output:
// da39a3ee5e6b4b0d3255bfef95601890afd80709

crypto.Hash.New() 関数で hash.Hash のインスタンスを生成している。 hash.Hash はこんな感じの interface 型である。

// Hash is the common interface implemented by all hash functions.
type Hash interface {
    // Write (via the embedded io.Writer interface) adds more data to the running hash.
    // It never returns an error.
    io.Writer

    // Sum appends the current hash to b and returns the resulting slice.
    // It does not change the underlying hash state.
    Sum(b []byte) []byte

    // Reset resets the Hash to its initial state.
    Reset()

    // Size returns the number of bytes Sum will return.
    Size() int

    // BlockSize returns the hash's underlying block size.
    // The Write method must be able to accept any amount
    // of data, but it may operate more efficiently if all writes
    // are a multiple of the block size.
    BlockSize() int
}

つまり,このインタフェースを備えていれば自前の hash アルゴリズムを簡単に組み込むことができるわけだ。 言い方を変えると, hash.Value() 関数で実際に hash 値を計算するにはこのパッケージだけではダメで, hash アルゴリズムを実装するパッケージをインポートする必要がある。

以下にアルゴリズム毎に必要なパッケージを示す。

hash algorithm import package
crypto.MD4 golang.org/x/crypto/md4
crypto.MD5 crypto/md5
crypto.SHA1 crypto/sha1
crypto.SHA224 crypto/sha256
crypto.SHA256 crypto/sha256
crypto.SHA384 crypto/sha512
crypto.SHA512 crypto/sha512
crypto.SHA512_224 crypto/sha512
crypto.SHA512_256 crypto/sha512
crypto.RIPEMD160 golang.org/x/crypto/ripemd160
crypto.SHA3_224 golang.org/x/crypto/sha3
crypto.SHA3_256 golang.org/x/crypto/sha3
crypto.SHA3_384 golang.org/x/crypto/sha3
crypto.SHA3_512 golang.org/x/crypto/sha3
crypto.BLAKE2s_256 golang.org/x/crypto/blake2s
crypto.BLAKE2b_256 golang.org/x/crypto/blake2b
crypto.BLAKE2b_384 golang.org/x/crypto/blake2b
crypto.BLAKE2b_512 golang.org/x/crypto/blake2b

この中から必要なパッケージを main パッケージでブランク・インポートする2。 全部インポートするならこんな感じ。

package main

import (
    _ "crypto/md5"
    _ "crypto/sha1"
    _ "crypto/sha256"
    _ "crypto/sha512"

    _ "golang.org/x/crypto/blake2b"
    _ "golang.org/x/crypto/blake2s"
    _ "golang.org/x/crypto/md4"
    _ "golang.org/x/crypto/ripemd160"
    _ "golang.org/x/crypto/sha3"
)

これを CLI (Command-Line Interface) にしたのが以下に示す hash コマンドである。

$ hash -h
Usage:
  hash [flags] [binary file]

Flags:
  -a, --algo string      hash algorithm (default "sha256")
  -c, --compare string   compare hash value
  -h, --help             help for hash

サイズがゼロの空ファイル empty.txt を作って試してみると

$ hash -a sha1 empty.txt
da39a3ee5e6b4b0d3255bfef95601890afd80709

となる。 パイプにも対応してるので

$ cat empty.txt | hash -a sha1
da39a3ee5e6b4b0d3255bfef95601890afd80709

とすることもできる。 さらに -c オプションで hash 値の計算結果をリファレンスの値と比較できる。

$ hash -a sha1 empty.txt -c da39a3ee5e6b4b0d3255bfef95601890afd80709
matched

なお,アルゴリズムには md4, md5, sha1, sha224, sha256, sha384, sha512, sha512/224, sha512/256, ripemd160, sha3-224, sha3-256, sha3-384, sha3-512, blake2s, blake2b/256, blake2b/384, blake2b/512 を指定できるようにした。 既定は sha256

例えば,これで dep の実行モジュールの正当性確認が少し楽になる。 depリリースページで Windows 用の実行モジュールと SHA256 値を記述したファイルをダウンロードする。

  • dep-windows-amd64
  • dep-windows-amd64.sha256

dep-windows-amd64.sha256 の中身が

034f8cf6c225fde51aa025376df12450832f111b39050a7ec451a9ec2ce2cb54  release/dep-windows-amd64

とするなら

$ hash dep-windows-amd64 -c 034f8cf6c225fde51aa025376df12450832f111b39050a7ec451a9ec2ce2cb54
matched

で一発確認できる。 確認できたら dep-windows-amd64dep.exe にリネームして使えばよい。

ブックマーク

参考図書

photo
プログラミング言語Go
アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)
丸善出版 2016-06-20 (Release 2021-07-13)
Kindle版
B099928SJD (ASIN)
評価     

Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想はこちら

reviewed by Spiegel on 2021-05-22 (powered by PA-APIv5)

photo
暗号技術入門 第3版 秘密の国のアリス
結城 浩 (著)
SBクリエイティブ 2015-08-25 (Release 2015-09-17)
Kindle版
B015643CPE (ASIN)
評価     

SHA-3 や Bitcoin/Blockchain など新しい知見や技術要素を大幅追加。暗号技術を使うだけならこれ1冊でとりあえず無問題。

reviewed by Spiegel on 2015-09-20 (powered by PA-APIv5)


  1. Windows 標準ツールとしては, PowerShell 4.0 以上が入っている PC なら, Get-FileHash コマンドレットが使える。 Windows 7 の場合は “Windows Management Framework 4.0” をインストールすることで PowerShell 4.0 にアップグレードできる。 ↩︎

  2. ブランク・インポートは main パッケージでしないと golint に怒られるのよ。まぁ言いたいことは分かるけど。 ↩︎