Go Argon2 Hash Code Example (Online Runner)

Go Argon2id/Argon2i hashing examples with iterations, memory, parallelism, salt encoding, and optional secret inputs.

Online calculator: use the site Argon2 text tool.

Note: This snippet requires locally installed dependencies and will not run in the online runner. Run it locally with: go mod init argon2-demo && go get golang.org/x/crypto/argon2 && go run argon2_basic.go

Calculation method

Use golang.org/x/crypto/argon2 to derive a hash with configurable iterations, memory (KiB), and parallelism. The helper returns the raw hash hex; you can store the salt alongside it.

Implementation notes

  • Package: golang.org/x/crypto/argon2 provides Argon2id and Argon2i.
  • Implementation: when no salt is provided, the helper generates a random 16-byte salt.
  • Notes: Argon2d is not available in x/crypto; use Argon2id or Argon2i for password hashing.

Text hashing example

go
package main

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"

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

func argon2idText(password string, salt []byte, iterations, memoryKiB uint32, parallelism uint8, hashLen uint32) string {
	hash := argon2.IDKey([]byte(password), salt, iterations, memoryKiB, parallelism, hashLen)
	return hex.EncodeToString(hash)
}

func main() {
	salt := make([]byte, 16)
	if _, err := rand.Read(salt); err != nil {
		panic(err)
	}
	value := argon2idText("password", salt, 3, 65536, 1, 32)
	fmt.Println(value)
}

Complete script (implementation + tests)

go
package main

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"fmt"

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

type Variant string

type SaltEncoding string

const (
	Argon2id Variant = "argon2id"
	Argon2i  Variant = "argon2i"
	Argon2d  Variant = "argon2d"
)

const (
	SaltHex    SaltEncoding = "hex"
	SaltBase64 SaltEncoding = "base64"
	SaltText   SaltEncoding = "text"
)

func decodeSalt(value string, encoding SaltEncoding) ([]byte, error) {
	if value == "" {
		salt := make([]byte, 16)
		if _, err := rand.Read(salt); err != nil {
			return nil, err
		}
		return salt, nil
	}
	switch encoding {
	case SaltHex:
		return hex.DecodeString(value)
	case SaltBase64:
		return base64.StdEncoding.DecodeString(value)
	case SaltText:
		fallthrough
	default:
		return []byte(value), nil
	}
}

func argon2Text(password string, variant Variant, iterations, memoryKiB uint32, parallelism uint8, hashLen uint32, salt string, saltEnc SaltEncoding, secret string) (string, []byte, error) {
	if variant == Argon2d {
		return "", nil, errors.New("argon2d is not supported by golang.org/x/crypto/argon2")
	}
	saltBytes, err := decodeSalt(salt, saltEnc)
	if err != nil {
		return "", nil, err
	}
	pwd := []byte(password)
	if secret != "" {
		pwd = append(pwd, []byte(secret)...)
	}

	var hash []byte
	if variant == Argon2i {
		hash = argon2.Key(pwd, saltBytes, iterations, memoryKiB, parallelism, hashLen)
	} else {
		hash = argon2.IDKey(pwd, saltBytes, iterations, memoryKiB, parallelism, hashLen)
	}
	return hex.EncodeToString(hash), saltBytes, nil
}

func main() {
	hexHash, salt, err := argon2Text("password", Argon2id, 3, 65536, 1, 32, "73616c74", SaltHex, "")
	if err != nil {
		panic(err)
	}
	fmt.Println("argon2id hash=", hexHash)
	fmt.Println("salt(hex)=", hex.EncodeToString(salt))
}