cryptonight hash functions in go assembler
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Loki Verloren 45bdbf8b24
Merge remote-tracking branch 'origin/master'
6 months ago
.circleci retargeted 6 months ago
cmd/cnhash retargeted 6 months ago
groestl retargeted 6 months ago
internal retargeted 6 months ago
jh retargeted 6 months ago
.gitattributes split assembly files 1 year ago
.gitignore clean files, add README 1 year ago
LICENSE clean files, add README 1 year ago
README.adoc retargeted 6 months ago
arith_amd64.go split v2Sqrt and tests 1 year ago
arith_amd64.s rename some variables 1 year ago
arith_ref.go fix ref function signature 1 year ago
arith_test.go split v2Sqrt and tests 1 year ago
cryptonight.go retargeted 6 months ago
cryptonight_test.go retargeted 6 months ago
difficulty.go diff: fix algorithm 1 year ago
difficulty_test.go diff: fix algorithm 1 year ago
example_test.go update to the latest v2 tweak 1 year ago
final_hash.go retargeted 6 months ago
go.mod updating mod 6 months ago
go.sum updating mod 6 months ago
sum_amd64.go retargeted 6 months ago
sum_amd64_test.go test: early return 1 year ago
sum_defs_amd64.h rename some variables 1 year ago
sum_generic.go assembly implementation of memhard for amd64 1 year ago
sum_ref.go retargeted 6 months ago
sum_ref_test.go split v2Sqrt and tests 1 year ago
sum_v0_amd64.s asm: lint 1 year ago
sum_v1_amd64.s asm: lint 1 year ago
sum_v2_amd64.s v2: asm: reduce move from xmm 1 year ago



GoDoc tag CircleCI Codecov Go Report Card License

Pure Go/ASM implementation of CryptoNight hash function and some of its variant, without any CGO binding.


  • Support Monero v7 variant, and also the upcoming variant 2!

  • No CGO hell, making builds easier and faster.

  • Hardware acceleration available for amd64 architecture.

  • Use of an internal sync.Pool to manage caches, since it is memory hard.


$ go get -u

A simple CLI utility is also available with go get -u

Usage of cnhash:
        Benchmark mode, don't do anything else.
  -in-file string
        Read input from file instead of stdin.
        Read input in hex instead of binary.
        Append the difficulty of the result hash to the output. If -out-binary is not given,
the difficulty will be appeneded to the output in decimal with comma separated (CSV friendly)
, otherwise it will be appeneded to the hash binary (which is 32 bytes long) directly, in 8
bytes little endian.
        Produce output in binary (little endian) instead of hex.
  -out-file string
        Produce output to file instead of stdout.
  -variant int
        Set CryptoNight variant, default 0. This applies to benchmark mode as well.


package main

import (


func main() {
    blob := []byte("Hello, 世界")
    fmt.Printf("%x\n", cryptonight.Sum(blob, 0)) // original
    // Output: 0999794e4e20d86e6a81b54495aeb370b6a9ae795fb5af4f778afaf07c0b2e0e

    blob = []byte("variant 1 requires at least 43 bytes of input.")
    fmt.Printf("%x\n", cryptonight.Sum(blob, 1)) // variant 1
    // Output: 261124c5a6dca5d4aa3667d328a94ead9a819ae714e1f1dc113ceeb14f1ecf99

    blob = []byte("Monero is cash for a connected world. It’s fast, private, and secure.")
    fmt.Printf("%x\n", cryptonight.Sum(blob, 2)) // variant 2
    // Output: abb61f40468c70234051e4bb5e8b670812473b2a71e02c9633ef94996a621b96

Tested architectures

  • amd64 (w/ AVX, SSE, AES)

  • amd64 (w/o AVX, SSE, AES)

  • 386

  • arm64


CPU: 4 x Intel® Xeon® CPU E3-1270 v3 @ 3.50GHz

goos: linux
goarch: amd64
BenchmarkSum/v0-4            100   20208070 ns/op   21584 B/op   2 allocs/op
BenchmarkSum/v1-4            100   20535318 ns/op   21584 B/op   2 allocs/op
BenchmarkSum/v2-4            100   22328893 ns/op   21584 B/op   2 allocs/op
BenchmarkSum/v0-parallel-4   100   10798945 ns/op   42664 B/op   2 allocs/op
BenchmarkSum/v1-parallel-4   100   10316040 ns/op   42655 B/op   2 allocs/op
BenchmarkSum/v2-parallel-4   100   11740615 ns/op   42661 B/op   2 allocs/op


While this repository is already out-of-box, which means what you need to do to use it in your code is just a go get (or dep ensure -add whatsoever), in case you want to hack on this library, some additional steps are required since it uses code generation.


If you modified a source file in this library that uses C-kind macros (the comments tells), in order to expand them and generate the final code, cpp(1) is needed, which a part of GCC toolchain and should be already available if you have installed gcc (or MinGW for Windows) in your machine.

Once some modification is made in a file that used macro, simply use go generate to run the gcc preprocessor on them.

Packages information

From Go’s crypto/aes. Since CryptoNight’s use of AES is quite non-standard and not intended for encryption, you must use this package this package with care for project that’s not CryptoNight associated.

From Go’s All CryptoNight specific additional works are made in cn.go only; other files are untouched at all.

Grøstl-256 implementation. It is directly ported from C and not quite optimized.

JH-256 implementation. It is directly ported from C and not quite optimized.

Tests, coverage and benchmarks

$ go test -v -race -coverprofile=coverage.txt -covermode=atomic
$ go tool cover -html=coverage.txt
$ go test -v -run=^$ -bench=. -benchmem


  • ❏ ARM64-specific optimization

  • ✓ Tests on other architectures

  • ✓ Improve performance for variant 2

  • ❏ Improve performance for groestl and jh

  • ✓ Try a nearly full assembly implementation (except for the final hash) for amd64


If you find this lib helpful, maybe consider buying me a cup of coffee at





Much thanks.