crypto/sha256.New în Go

Creează un calculator SHA-256 în care scrii datele pe bucăți (ex. cu io.Copy dintr-un fișier), apoi citești suma cu Sum(nil).

Sintaxă
func New() hash.Hash

// hash.Hash: io.Writer + Sum(b []byte) []byte + Reset() + Size()

Ce face crypto/sha256.New

sha256.New() returnează un hash.Hash, care este și un io.Writer: scrii în el datele în oricâte bucăți (h.Write, fmt.Fprint(h, ...), io.Copy(h, fisier)), iar la final h.Sum(nil) returnează amprenta ca []byte. Rezultatul este același ca la Sum256 pe toate datele lipite.

Așa calculezi hash-ul unui fișier de mai mulți gigaocteți fără să-l citești tot în memorie. h.Reset() golește calculatorul pentru alte date. Aceeași formă o folosește și hmac.New(sha256.New, cheie) pentru semnături cu cheie secretă (HMAC), de exemplu la verificarea webhook-urilor.

Ce returnează

Un hash.Hash nou.

Exemple

Exemplul 1: Suma unui fișier citit în flux

package main

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

func main() {
	os.WriteFile("backup.sql", []byte(strings.Repeat("INSERT INTO produse VALUES (1, 'cafea');\n", 1000)), 0o644)

	f, err := os.Open("backup.sql")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	h := sha256.New()
	n, err := io.Copy(h, f)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%d octeți, sha256 = %x\n", n, h.Sum(nil))

	tot, _ := os.ReadFile("backup.sql")
	fmt.Println("Același rezultat ca Sum256:", fmt.Sprintf("%x", sha256.Sum256(tot)) == fmt.Sprintf("%x", h.Sum(nil)))
}

Rezultat

41000 octeți, sha256 = 49ec0bf57514e4df3a44474490e4b6862815bae6d3aa5383834537dab3a974e8
Același rezultat ca Sum256: true

Exemplul 2: Bucăți scrise pe rând și semnătură HMAC

package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"fmt"
)

func main() {
	h := sha256.New()
	h.Write([]byte("Ana "))
	h.Write([]byte("are "))
	fmt.Fprint(h, "mere")
	fmt.Printf("bucăți:  %x\n", h.Sum(nil))
	fmt.Printf("dintr-o: %x\n", sha256.Sum256([]byte("Ana are mere")))

	mac := hmac.New(sha256.New, []byte("cheie-secreta-webhook"))
	mac.Write([]byte(`{"comanda":1001,"stare":"platita"}`))
	semnatura := mac.Sum(nil)
	fmt.Printf("HMAC:    %x\n", semnatura)

	verificare := hmac.New(sha256.New, []byte("cheie-secreta-webhook"))
	verificare.Write([]byte(`{"comanda":1001,"stare":"platita"}`))
	fmt.Println("Semnătură validă:", hmac.Equal(semnatura, verificare.Sum(nil)))
}

Rezultat

bucăți:  04c43a6d8236091578fcbebadfab4940a1f2387d3b21468f2eb6e0e01824089e
dintr-o: 04c43a6d8236091578fcbebadfab4940a1f2387d3b21468f2eb6e0e01824089e
HMAC:    2fe738637ebbb3c0719f98f43d437c1519184e2a33e54c38ccbba0c692e3efc1
Semnătură validă: true

Greșeli frecvente

  • Crezi că h.Sum(date) calculează hash-ul lui date. Argumentul este un slice la care se adaugă suma; datele se scriu cu Write, iar suma se citește cu Sum(nil).
  • Folosești același hash.Hash din mai multe goroutine: nu este sigur. Creează câte unul pentru fiecare.

Comenzi înrudite

  • crypto/sha256.Sum256: Calculează amprenta SHA-256 a unor date: 32 de octeți (64 de cifre hex) care se schimbă complet la orice modificare.
  • crypto/md5.Sum: Calculează suma MD5 (16 octeți, 32 cifre hex); bună doar pentru sume de control, nu pentru securitate.
  • encoding/hex.EncodeToString: Scrie octeții în hexazecimal (două cifre 0-9a-f pe octet) și înapoi; forma obișnuită pentru hash-uri și chei.