如何在Go中计算sha256文件校验和

huangapple go评论75阅读模式
英文:

How to calculate sha256 file checksum in Go

问题

我需要一个用于Windows的实用程序,用于计算sha256文件校验和,以便在我下载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)))
}

如何使其使用流式处理,以便适用于任何文件大小。

英文:

I need utility for Windows that calculates sha256 file checksum so that when I download
fedora I can verify checksum from here: https://fedoraproject.org/static/checksums/Fedora-18-i386-CHECKSUM

Microsoft utility from http://support.microsoft.com/kb/889768 does only md5 and sha1.

I don't want to use other downloadable tools that are not signed and not available from https or from sources that I don't know about, because it does not make any sense to download unsigned code over unencrypted connection or from untrusted source to verify signature of another code to trust it.

Luckily google provides possibility to use https for all downloads so I can download Go over secure connection and start from there.

Here is simple code that does that for a small file, but it's not very good for big files because it's not streaming.

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

How to make it to use streams so that it works on any file size.

答案1

得分: 43

The crypto/sha256 godoc actually has a snippet that shows how to do that (it's basically the same code as 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))
}
英文:

The crypto/sha256 godoc actually has a snippet that shows how to do that (it's basically the same code as 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))
}

答案2

得分: 37

SHA256哈希器实现了io.Writer接口,因此一种选择是使用io.Copy()函数将数据从适当的io.Reader以块的形式复制。类似下面的代码应该可以实现:

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)
}
英文:

The SHA256 hasher implements the io.Writer interface, so one option would be to use the io.Copy() function to copy the data from an appropriate io.Reader in blocks. Something like this should do:

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

答案3

得分: 10

完整的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

英文:

Full example of 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 does not omits leading 0 bytes, so fmt.Println(hex.EncodeToString([]byte{0x00, 0x00, 0xA, 0xB, 0xC})) gives
00000a0b0c

huangapple
  • 本文由 发表于 2013年4月8日 20:34:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/15879136.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定