28

我需要计算 sha256 文件校验和的 Windows 实用程序,这样当我下载 fedora 时,我可以从这里验证校验和:https ://fedoraproject.org/static/checksums/Fedora-18-i386-CHECKSUM

来自http://support.microsoft.com/kb/889768的Microsoft 实用程序仅执行 md5 和 sha1。

我不想使用其他未签名且无法从 https 或我不知道的来源获得的可下载工具,因为通过未加密的连接或从不受信任的来源下载未签名的代码进行验证没有任何意义另一个代码的签名以信任它。

幸运的是,谷歌提供了使用 https 进行所有下载的可能性,因此我可以通过安全连接下载 Go 并从那里开始。

这是对小文件执行此操作的简单代码,但对大文件不是很好,因为它不是流式传输的。

package main

import (
    "io/ioutil"
    "crypto/sha256"
    "os"
    "log"
    "encoding/hex"
)

func main() {
    hasher := sha256.New()
    s, err := ioutil.ReadFile(os.Args[1])    
    hasher.Write(s)
    if err != nil {
        log.Fatal(err)
    }

    os.Stdout.WriteString(hex.EncodeToString(hasher.Sum(nil)))
}

如何使它使用流,以便它适用于任何文件大小。

4

3 回答 3

30

SHA256 散列器实现了该io.Writer接口,因此一种选择是使用该io.Copy()函数从适当io.Reader的 in 块中复制数据。这样的事情应该做:

f, err := os.Open(os.Args[1])
if err != nil {
    log.Fatal(err)
}
defer f.Close()
if _, err := io.Copy(hasher, f); err != nil {
    log.Fatal(err)
}
于 2013-04-09T03:20:19.203 回答
30

crypto/sha256 godoc实际上有一个片段显示了如何做到这一点(它与 James 的代码基本相同):

package main

import (
  "crypto/sha256"
  "fmt"
  "io"
  "log"
  "os"
)

func main() {
  f, err := os.Open("file.txt")
  if err != nil {
    log.Fatal(err)
  }
  defer f.Close()

  h := sha256.New()
  if _, err := io.Copy(h, f); err != nil {
    log.Fatal(err)
  }

  fmt.Printf("%x", h.Sum(nil))
}
于 2017-07-16T00:48:16.657 回答
8

md5sum 的完整示例:

func md5sum(filePath string) (string, error) {
    file, err := os.Open(filePath)
    if err != nil {
        return "", err
    }
    defer file.Close()

    hash := md5.New()
    if _, err := io.Copy(hash, file); err != nil {
        return "", err
    }
    return hex.EncodeToString(hash.Sum(nil)), nil
}

EncodeToString不省略前导 0 字节,因此fmt.Println(hex.EncodeToString([]byte{0x00, 0x00, 0xA, 0xB, 0xC}))给出 00000a0b0c

于 2016-11-05T09:12:45.297 回答