SHA-512 in Go lives in crypto/sha512. It outputs a 64-byte (512-bit) digest, usually shown as 128 hexadecimal characters—double the width of SHA-256. This guide mirrors a practical layout: quick reference, string and file hashing, verification, streaming, salted verification patterns (not password storage), comparison with SHA-256, common use cases, and pitfalls. For the 256-bit variant, see Golang SHA-256. For real encryption, see encrypt and decrypt data in Go; here we only cover hashing.
Examples were run with Go 1.24 on Linux. Hex lines match
printf '%s' '…' | sha512sumfor the same bytes (watch for accidental newlines).
SHA512 in Go at a Glance
sha512.Sum512([]byte)→[64]byte— one-shot when the full message is already in memory.sha512.New()→hash.Hash— stream withWriteorio.Copy, thenSum(nil).- Hex:
fmt.Printf("%x", sum[:])orhex.EncodeToString(sum[:])(128 characters for SHA-512). - Verify files: stream with
io.Copy, compare[]bytedigests withbytes.Equalafterhex.DecodeStringon the expected value. - Keyed integrity:
hmac.New(sha512.New, key)— not raw SHA-512 of a secret alone.
Quick reference table for common SHA512 operations
| Task | API | Notes |
|---|---|---|
Hash small []byte |
sha512.Sum512 |
Returns [64]byte; slice with sum[:] for []byte. |
| Show hex | %x or hex.EncodeToString |
128 lowercase hex chars with %x. |
| Hash a file | io.Copy(sha512.New(), file) |
Constant memory streaming. |
| Incremental | h.Write chunks, then h.Sum(nil) |
Same hash.Hash contract as SHA-256. |
| Verify checksum | Decode hex, bytes.Equal |
Normalize spaces and case on the published string. |
| Keyed MAC | hmac.New(sha512.New, key) |
Compare with hmac.Equal. |
| Passwords | Not plain SHA-512 | Use bcrypt or Argon2. |
Generate a SHA512 Hash in Go
Hash a string using sha512.Sum512
sha512.Sum512(data []byte) [64]byte hashes the entire input at once.
package main
import (
"crypto/sha512"
"fmt"
)
func main() {
sum := sha512.Sum512([]byte("Hello GoLinuxCloud!"))
fmt.Printf("%x\n", sum)
}Run prints:
84ad5dfdd5265d37a3732986ffdee98fc0e635dbffa16f8771f5421cfb9c13dee61183d2ab8c90e647cf00daaa4e6141d2c2e40c4c39cbd42e3629c9076bff42Convert the hash to a hexadecimal string
Sum512 returns an array; slice to []byte for APIs that need a slice.
package main
import (
"crypto/sha512"
"encoding/hex"
"fmt"
)
func main() {
sum := sha512.Sum512([]byte("hello"))
fmt.Printf("fmt %%x: %x\n", sum)
fmt.Println("hex.Encode:", hex.EncodeToString(sum[:]))
}Run prints 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043 twice (same as printf '%s' 'hello' | sha512sum).
Hash Files Using SHA512
Calculate the SHA512 checksum of a file
Stream through hash.Hash so you do not read the whole file into RAM.
package main
import (
"crypto/sha512"
"fmt"
"io"
"os"
)
func main() {
payload := []byte("line one\nline two\n")
f, err := os.CreateTemp("", "sha512-*.txt")
if err != nil {
fmt.Println(err)
return
}
name := f.Name()
defer os.Remove(name)
if _, err := f.Write(payload); err != nil {
fmt.Println(err)
return
}
f.Close()
in, err := os.Open(name)
if err != nil {
fmt.Println(err)
return
}
defer in.Close()
h := sha512.New()
if _, err := io.Copy(h, in); err != nil {
fmt.Println(err)
return
}
fmt.Printf("%x\n", h.Sum(nil))
}Run prints 8bb21ebab8648a9bda3489580a0844b05fc2b1550d3672463b8eca3f01fc69750e4264b9995676ac9ced7f9038e69a55be0ea8143260c1b8227b1e3f5d56218f for that payload (matches printf 'line one\nline two\n' | sha512sum).
Verify a downloaded file using a SHA512 checksum
Decode the published hex, hash the file on disk, then compare. Trim and lowercase the published string in real tools.
package main
import (
"bytes"
"crypto/sha512"
"encoding/hex"
"fmt"
"io"
"os"
"strings"
)
func fileSHA512(path string) ([64]byte, error) {
f, err := os.Open(path)
if err != nil {
return [64]byte{}, err
}
defer f.Close()
h := sha512.New()
if _, err := io.Copy(h, f); err != nil {
return [64]byte{}, err
}
var out [64]byte
copy(out[:], h.Sum(nil))
return out, nil
}
func main() {
const wantHex = "8bb21ebab8648a9bda3489580a0844b05fc2b1550d3672463b8eca3f01fc69750e4264b9995676ac9ced7f9038e69a55be0ea8143260c1b8227b1e3f5d56218f"
f, _ := os.CreateTemp("", "verify-*.txt")
defer os.Remove(f.Name())
_, _ = f.Write([]byte("line one\nline two\n"))
_ = f.Close()
want, err := hex.DecodeString(strings.TrimSpace(strings.ToLower(wantHex)))
if err != nil || len(want) != sha512.Size {
fmt.Println("bad expected hex")
return
}
got, err := fileSHA512(f.Name())
if err != nil {
fmt.Println(err)
return
}
fmt.Println("checksum OK:", bytes.Equal(got[:], want))
}Run prints checksum OK: true.
SHA512 for Large Files and Streams
Using sha512.New with io.Copy
sha512.New() implements hash.Hash. io.Copy feeds the reader in chunks, which is the usual pattern for large bodies and network streams. The same pattern applies to *os.File, bytes.Buffer, HTTP response bodies, or any io.Reader.
package main
import (
"bytes"
"crypto/sha512"
"fmt"
"io"
)
func main() {
r := bytes.NewReader([]byte("chunked-read-example"))
h := sha512.New()
if _, err := io.Copy(h, r); err != nil {
panic(err)
}
fmt.Printf("%x\n", h.Sum(nil))
}Run prints:
6073c66efc39b52cd7fabdaadeee2493137136dc53ac3a3ad7adc932137790af2f24c4976bfb0d386b970ae0c08b71a03950387557f5932b452e65de69a3c917For a temp-file walkthrough, see Calculate the SHA512 checksum of a file above.
When to use sha512.New instead of sha512.Sum512
- Data arrives in pieces or from an
io.Reader. - The object is too large to buffer entirely.
- You reuse one hasher with
Resetin a loop. - You build
hmac.New(sha512.New, key).
If you already hold the full []byte, Sum512 is shorter.
The same module also offers Sum384, Sum512_224, and Sum512_256 when a protocol asks for a truncated SHA-512/SHA-384 width (pkg.go.dev).
SHA512 with Salt
Add a salt before hashing
For a custom integrity scheme you might hash append(salt, message...) or write salt then message into sha512.New(). The snippet below concatenates password and salt into one SHA-512 pass for a reproducible demo only.
package main
import (
"crypto/sha512"
"encoding/hex"
"fmt"
)
func digestPassword(password, salt []byte) string {
h := sha512.New()
h.Write(password)
h.Write(salt)
return hex.EncodeToString(h.Sum(nil))
}
func main() {
password := []byte("secret")
salt := []byte("demo-salt-16b!!")
stored := digestPassword(password, salt)
fmt.Println(stored)
fmt.Println("verify ok:", digestPassword([]byte("secret"), salt) == stored)
fmt.Println("verify bad:", digestPassword([]byte("wrong"), salt) == stored)
}Run prints the long hex line, then verify ok: true and verify bad: false.
Production salts must be random per user (for example from crypto/rand), and passwords should use Argon2 or bcrypt, not a single fast SHA-512 iteration.
Why SHA512 hashes cannot be decrypted
A digest is a one-way fingerprint: you cannot recover the input from the output. “Decrypt with salt” in search queries usually means “verify a candidate password by recomputing the digest.” That is comparison, not decryption. SHA-512 also does not provide confidentiality; pairing with a secret uses HMAC or AEAD encryption, not raw hashing.
SHA512 vs SHA256 in Go
| SHA-256 | SHA-512 | |
|---|---|---|
| Digest size | 32 bytes (64 hex chars) | 64 bytes (128 hex chars) |
| Typical use | Default interop, TLS, Git objects, many checksums | Protocols or policies that mandate wider SHA-2 output |
| Package | crypto/sha256 |
crypto/sha512 |
Performance and output size differences
Digest width is fixed: SHA-256 is 32 bytes; SHA-512 is 64 bytes (see the table above). Raw speed depends on CPU microarchitecture, clock boost, and whether the data is already hot in cache—always measure on your own binaries with realistic buffers.
Sample benchmark (one machine, for orientation only)
The following numbers come from go test -bench=. -benchmem -benchtime=1s -count=1 on linux/amd64, Go 1.24.4, CPU Intel Core Ultra 5 135U. Each benchmark hashes an all-zero buffer of the given size using one-shot sha256.Sum256 vs sha512.Sum512 (no heap allocations in this loop).
| Buffer | sha256.Sum256 |
sha512.Sum512 |
Time ratio (512 / 256) |
|---|---|---|---|
| 1 KiB | ~1.99 µs/op (~515 MB/s) | ~4.86 µs/op (~211 MB/s) | ~2.4× |
| 64 KiB | ~80 µs/op (~818 MB/s) | ~244 µs/op (~269 MB/s) | ~3.0× |
| 1 MiB | ~912 µs/op (~1150 MB/s) | ~3.11 ms/op (~337 MB/s) | ~3.4× |
On this run, SHA-512 was slower at every size, which is common on many laptop-class cores even though both use highly optimized assembly—your server or ARM box can rank differently. Re-run with testing.B and your real payload shapes; use benchstat if you compare changes over multiple commits.
Minimal benchmark you can copy into a module (for example internal/hashbench/sha_bench_test.go):
package hashbench
import (
"crypto/sha256"
"crypto/sha512"
"testing"
)
func benchSum256(size int, b *testing.B) {
data := make([]byte, size)
b.SetBytes(int64(size))
b.ResetTimer()
for i := 0; i < b.N; i++ {
sha256.Sum256(data)
}
}
func benchSum512(size int, b *testing.B) {
data := make([]byte, size)
b.SetBytes(int64(size))
b.ResetTimer()
for i := 0; i < b.N; i++ {
sha512.Sum512(data)
}
}
func BenchmarkSHA256_1KB(b *testing.B) { benchSum256(1024, b) }
func BenchmarkSHA512_1KB(b *testing.B) { benchSum512(1024, b) }
func BenchmarkSHA256_64KB(b *testing.B) { benchSum256(64*1024, b) }
func BenchmarkSHA512_64KB(b *testing.B) { benchSum512(64*1024, b) }
func BenchmarkSHA256_1MB(b *testing.B) { benchSum256(1024*1024, b) }
func BenchmarkSHA512_1MB(b *testing.B) { benchSum512(1024*1024, b) }Then from the module root: go test ./path/to/hashbench -bench=. -benchmem -benchtime=1s.
Choose SHA-256 unless you need the larger digest or a standard mandates SHA-512 explicitly.
Which algorithm should you choose?
Default to SHA-256 for new integrity work and broad ecosystem compatibility. Choose SHA-512 when a specification requires it, when you want a larger fingerprint without truncation, or when you standardize on SHA-512/384-style suites. For passwords, choose Argon2id or bcrypt regardless of SHA-2 size.
Common SHA512 Use Cases
File integrity verification
Same workflow as SHA-256: publish a .sha512 or SHA512SUMS file, recompute locally, compare digests (see verify a downloaded file).
Digital signatures and certificates
TLS, CMS, and certificate tooling may combine asymmetric keys with SHA-2 family digests; exact algorithms depend on the protocol version and cipher suite. In application code you rarely “pick SHA-512 for TLS” directly—libraries choose permitted pairs. SHA-512 appears in signing APIs where a standard specifies it.
Content fingerprinting
Use the hex digest (or a prefix) as a cache key or content address. Anyone who knows the input can recompute the digest, so this detects change, not secrecy.
HMAC-SHA512 example
package main
import (
"crypto/hmac"
"crypto/sha512"
"encoding/hex"
"fmt"
)
func main() {
k := []byte("key")
m := []byte("msg")
mac := hmac.New(sha512.New, k)
mac.Write(m)
fmt.Println(hex.EncodeToString(mac.Sum(nil)))
}Run prints 1e4b55b925ccc28ed90d9d18fc2393fcbe164c0d84e67e173cc5aa486b7afc106633c66bdc309076f5f8d9fdbbb62456f894f2c23377fbcc12f4ab2940eb6d70.
Common Mistakes and Security Notes
SHA512 is not encryption
Hashing produces a fixed-size digest with no secret key in the basic form; it does not hide data. Confidentiality needs encryption (for example AES-GCM) with proper key management.
SHA512 should not be used for password storage
A single SHA-512 (even with a salt) is far too fast for password guessing at scale. Use Argon2id, bcrypt, or scrypt with parameters tuned to your environment.
SHA512 cheat sheet (single source)
Runnable programs live in the sections above. The quick reference table lists APIs; repeating full programs at the end tends to drift (wrong file paths, half snippets). Copy from the verified blocks in this page instead of maintaining a second copy.
Summary
Use sha512.Sum512 for small in-memory buffers and sha512.New with io.Copy or Write for files and streams. Format digests as 128 hex characters. Verify downloads by decoding expected hex and comparing 64-byte digests. Treat “salted SHA-512” demos as illustration only—real passwords belong to Argon2/bcrypt. Prefer SHA-256 unless you need SHA-512’s width or a standard requires it; use HMAC when the design calls for a keyed MAC.
References
- Package crypto/sha512
- Package crypto/hmac
- Package golang.org/x/crypto/bcrypt
- Package golang.org/x/crypto/argon2
- FIPS 180-4

