惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Azure Blog
Microsoft Azure Blog
Cloudbric
Cloudbric
I
InfoQ
V
V2EX
博客园_首页
The Register - Security
The Register - Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
S
Secure Thoughts
Vercel News
Vercel News
Forbes - Security
Forbes - Security
云风的 BLOG
云风的 BLOG
PCI Perspectives
PCI Perspectives
L
LINUX DO - 最新话题
D
DataBreaches.Net
H
Hacker News: Front Page
Application and Cybersecurity Blog
Application and Cybersecurity Blog
B
Blog RSS Feed
A
About on SuperTechFans
N
News and Events Feed by Topic
Apple Machine Learning Research
Apple Machine Learning Research
Help Net Security
Help Net Security
Attack and Defense Labs
Attack and Defense Labs
N
Netflix TechBlog - Medium
Spread Privacy
Spread Privacy
F
Full Disclosure
Recorded Future
Recorded Future
AWS News Blog
AWS News Blog
博客园 - 【当耐特】
The Cloudflare Blog
T
Threatpost
T
Tor Project blog
Google DeepMind News
Google DeepMind News
C
CXSECURITY Database RSS Feed - CXSecurity.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
M
MIT News - Artificial intelligence
A
Arctic Wolf
C
Check Point Blog
Stack Overflow Blog
Stack Overflow Blog
T
Threat Research - Cisco Blogs
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News - Newest:
Hacker News - Newest: "LLM"
WordPress大学
WordPress大学
Cyberwarzone
Cyberwarzone
小众软件
小众软件
C
Cyber Attacks, Cyber Crime and Cyber Security
P
Proofpoint News Feed
Security Latest
Security Latest
The Last Watchdog
The Last Watchdog

Dizzy zone

Pangolin Private Resources With Domain Https About Redis is fast - I'll cache in Postgres n8n and large files Malicious Node install script on Google search Wrapping Go errors with caller info State of my Homelab 2025 My homelabs power consumption On Umami ML for related posts on Hugo Probabilistic Early Expiration in Go SQLC & dynamic queries Enums in Go Streaming Netdata metrics from TrueNAS SCALE SQL string constant gotcha Moving from Jenkins to Drone My new server: MSI Cubi 3 Silent My thoughts on Ansible® Profiling gin with pprof How I host this blog, CI and tooling Refactoring Go switch statements OAuth with Gin and Goth I made my own commenting server. Here's why. Why I hate OpenApi(swagger) IDE for GO Jenkins on raspberry pi 3 How I started my professional career Kestrel vs Gin vs Iris vs Express vs Fasthttp on EC2 nano Go's defer statement Self-hosted disqus alternative for 5$ a month Why I like go Speeding hexo (or any page) for PageSpeed insights Starting a blog with hexo and AWS S3
BLAKE2b performance on Apple Silicon
Vik · 2025-03-27 · via Dizzy zone

For work, I was going to store some hashed tokens in a database. I was going to keep it simple and go with HMAC-SHA256 for it but having recently read Jean-Philippe Aumasson’s book “Serious Cryptography” I remembered that BLAKE2 should be quicker:

BLAKE2 was designed with the following ideas in mind:

It should be faster than all previous hash standards

Cool, I thought, let’s consider BLAKE2 then. First, let’s write a simple benchmark to see just how much faster BLAKE2 would be than HMAC-SHA256. Performance is not important for my use case as the hashing will almost certainly not be a bottleneck but I was curious. So I write a benchmark:

import (
	"crypto/hmac"
	"crypto/rand"
	"crypto/sha256"
	"log"
	"testing"

	"golang.org/x/crypto/blake2b"
)

func BenchmarkHashes(b *testing.B) {
	token := []byte("some-api-token")
	secretKey := generateSecretKey()

	b.ResetTimer()

	_ = b.Run("HMACSHA256", func(b *testing.B) {
		for b.Loop() {
			_ = HMACSHA256(token, secretKey)
		}
	})

	_ = b.Run("BLAKE2b", func(b *testing.B) {
		for b.Loop() {
			_ = BLAKE2b(token, secretKey)
		}
	})
}

func generateSecretKey() []byte {
	key := make([]byte, 32)
	_, err := rand.Read(key)
	if err != nil {
		panic(err)
	}
	return key
}

func HMACSHA256(token []byte, secretKey []byte) []byte {
	h := hmac.New(sha256.New, secretKey)
	h.Write(token)
	return h.Sum(nil)
}

func BLAKE2b(token []byte, secretKey []byte) []byte {
	hasher, err := blake2b.New256(secretKey)
	if err != nil {
		log.Fatal(err)
	}
	hasher.Write(token)
	return hasher.Sum(nil)
}

Run it and the results are:

cpu: Apple M1 Max
BenchmarkHashes/HMACSHA256-10         	 3442680	       341.0 ns/op	     512 B/op	       6 allocs/op
BenchmarkHashes/BLAKE2b-10            	 1966382	       584.0 ns/op	     416 B/op	       2 allocs/op

OK… So BLAKE2 is slower than HMAC-SHA256. Yes, we have less allocations which is nice, but it does take quite a few more CPU cycles. My first thought is that it might indeed be faster but only if the input is like way, way longer. So I switch to the following token:

	token := []byte(strings.Repeat("some-api-token", 10000))
cpu: Apple M1 Max
BenchmarkHashes/HMACSHA256-10         	   19536	     59946 ns/op	     512 B/op	       6 allocs/op
BenchmarkHashes/BLAKE2b-10            	    6452	    190926 ns/op	     416 B/op	       2 allocs/op

Hmmmm… This is even worse. Now, it could be that we’re dealing with a non optimal implementation. SHA256 is implemented in the stdlib in Go and very likely well optimized, whereas the BLAKE2 implementation I’m using comes from the golang.org/x/crypto package. Perhaps we can find a better one. The first search result recommends github.com/minio/blake2b-simd which has been archived since 2018. Not promising, but let’s give it a shot.

import (
    blakeMinio "github.com/minio/blake2b-simd"
)

func BLAKE2bMinio(token []byte, secretKey []byte) []byte {
	hasher := blakeMinio.NewMAC(32, secretKey)
	hasher.Write(token)
	return hasher.Sum(nil)
}

These are the results with the original token.

cpu: Apple M1 Max
BenchmarkHashes/HMACSHA256-10         	 3622322	       316.7 ns/op	     512 B/op	       6 allocs/op
BenchmarkHashes/BLAKE2b-10            	 2881012	       415.6 ns/op	     416 B/op	       2 allocs/op
BenchmarkHashes/BLAKE2b-minio-10       	 2138151	       566.4 ns/op	     480 B/op	       2 allocs/op

So this is even slower… I quickly glance over the codebase of github.com/minio/blake2b-simd and notice all the architecture specific files but there aren’t any for ARM architecture. Let’s try on a machine with an AMD64 processor.

cpu: Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
BenchmarkHashes/HMACSHA256-4         	  761613	      1488 ns/op	     512 B/op	       6 allocs/op
BenchmarkHashes/BLAKE2b-4            	 2287569	       566.9 ns/op	     416 B/op	       2 allocs/op
BenchmarkHashes/BLAKE2b-minio-4      	 1541990	       765.4 ns/op	     480 B/op	       2 allocs/op

Right, so it seems that the implementations I’m using are only optimized for AMD64. Or are they? One final test, I spin up an ARM based VPS on Hetzner to test it out. Note, that since the benchmark was not able to determine the exact CPU model the CPU line was omitted.

BenchmarkHashes/HMACSHA256-2         	 1000000	      1007 ns/op	       512 B/op	       6 allocs/op
BenchmarkHashes/BLAKE2b-2            	 1367085	       879.6 ns/op	       416 B/op	       2 allocs/op
BenchmarkHashes/BLAKE2b-minio-2      	 1123965	      1080 ns/op	       480 B/op	       2 allocs/op

So with this, it seems that the issue only occurs on Apple Silicon processors. In the benchmarks with other processors, the BLAKE2b does win. I’m not entirely sure what causes this as CPU architectures are not my strong suite. If you do - please let me know by posting a comment.