mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-27 02:09:27 +00:00
109 lines
No EOL
2.5 KiB
Go
109 lines
No EOL
2.5 KiB
Go
//go:build arm64 && !purego
|
|
|
|
package keccak
|
|
|
|
import (
|
|
"runtime"
|
|
|
|
"golang.org/x/crypto/sha3"
|
|
"golang.org/x/sys/cpu"
|
|
)
|
|
|
|
// Apple Silicon always has Armv8.2-A SHA3 extensions (VEOR3, VRAX1, VXAR, VBCAX).
|
|
// On other ARM64 platforms, detect at runtime via CPU feature flags.
|
|
// When SHA3 is unavailable, falls back to x/crypto/sha3.
|
|
var useSHA3 = runtime.GOOS == "darwin" || runtime.GOOS == "ios" || cpu.ARM64.HasSHA3
|
|
|
|
//go:noescape
|
|
func keccakF1600(a *[200]byte)
|
|
|
|
//go:noescape
|
|
func xorAndPermute(state *[200]byte, buf *byte)
|
|
|
|
// Sum256 computes the Keccak-256 hash of data. Zero heap allocations when SHA3 is available.
|
|
func Sum256(data []byte) [32]byte {
|
|
if !useSHA3 {
|
|
return sum256XCrypto(data)
|
|
}
|
|
return sum256Sponge(data)
|
|
}
|
|
|
|
func sum256XCrypto(data []byte) [32]byte {
|
|
h := sha3.NewLegacyKeccak256()
|
|
h.Write(data)
|
|
var out [32]byte
|
|
h.Sum(out[:0])
|
|
return out
|
|
}
|
|
|
|
// Hasher is a streaming Keccak-256 hasher.
|
|
// Uses NEON SHA3 assembly when available, x/crypto/sha3 otherwise.
|
|
type Hasher struct {
|
|
sponge
|
|
xc KeccakState // x/crypto fallback
|
|
}
|
|
|
|
// Reset resets the hasher to its initial state.
|
|
func (h *Hasher) Reset() {
|
|
if useSHA3 {
|
|
h.sponge.Reset()
|
|
} else {
|
|
if h.xc == nil {
|
|
h.xc = sha3.NewLegacyKeccak256().(KeccakState)
|
|
} else {
|
|
h.xc.Reset()
|
|
}
|
|
}
|
|
}
|
|
|
|
// Write absorbs data into the hasher.
|
|
// Panics if called after Read.
|
|
func (h *Hasher) Write(p []byte) (int, error) {
|
|
if !useSHA3 {
|
|
if h.xc == nil {
|
|
h.xc = sha3.NewLegacyKeccak256().(KeccakState)
|
|
}
|
|
return h.xc.Write(p)
|
|
}
|
|
return h.sponge.Write(p)
|
|
}
|
|
|
|
// Sum256 finalizes and returns the 32-byte Keccak-256 digest.
|
|
// Does not modify the hasher state.
|
|
func (h *Hasher) Sum256() [32]byte {
|
|
if !useSHA3 {
|
|
if h.xc == nil {
|
|
return Sum256(nil)
|
|
}
|
|
var out [32]byte
|
|
h.xc.Sum(out[:0])
|
|
return out
|
|
}
|
|
return h.sponge.Sum256()
|
|
}
|
|
|
|
// Sum appends the current Keccak-256 digest to b and returns the resulting slice.
|
|
// Does not modify the hasher state.
|
|
func (h *Hasher) Sum(b []byte) []byte {
|
|
if !useSHA3 {
|
|
if h.xc == nil {
|
|
d := Sum256(nil)
|
|
return append(b, d[:]...)
|
|
}
|
|
return h.xc.Sum(b)
|
|
}
|
|
return h.sponge.Sum(b)
|
|
}
|
|
|
|
// Read squeezes an arbitrary number of bytes from the sponge.
|
|
// On the first call, it pads and permutes, transitioning from absorbing to squeezing.
|
|
// Subsequent calls to Write will panic. It never returns an error.
|
|
func (h *Hasher) Read(out []byte) (int, error) {
|
|
if !useSHA3 {
|
|
if h.xc == nil {
|
|
h.xc = sha3.NewLegacyKeccak256().(KeccakState)
|
|
}
|
|
return h.xc.Read(out)
|
|
}
|
|
return h.sponge.Read(out)
|
|
} |