This document covers symmetric encryption algorithms including modern stream ciphers (ChaCha20, Salsa20) and legacy block ciphers provided by golang.org/x/crypto.
ChaCha20-Poly1305 is an authenticated encryption with associated data (AEAD) algorithm defined in RFC 8439. It provides both confidentiality and authenticity.
const (
KeySize = 32 // Key size in bytes
NonceSize = 12 // Nonce size for ChaCha20-Poly1305
NonceSizeX = 24 // Nonce size for XChaCha20-Poly1305
Overhead = 16 // Authentication tag overhead in bytes
)// New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key.
func New(key []byte) (cipher.AEAD, error)
// NewX returns a XChaCha20-Poly1305 AEAD that uses the given 256-bit key.
// XChaCha20-Poly1305 is a variant with a larger nonce size that requires less nonce management.
func NewX(key []byte) (cipher.AEAD, error)package main
import (
"crypto/rand"
"fmt"
"golang.org/x/crypto/chacha20poly1305"
)
func main() {
// Generate a random key
key := make([]byte, chacha20poly1305.KeySize)
rand.Read(key)
// Create AEAD cipher
aead, err := chacha20poly1305.New(key)
if err != nil {
panic(err)
}
// Encrypt
nonce := make([]byte, aead.NonceSize())
rand.Read(nonce)
plaintext := []byte("secret message")
additionalData := []byte("metadata")
ciphertext := aead.Seal(nil, nonce, plaintext, additionalData)
fmt.Printf("Ciphertext: %x\n", ciphertext)
// Decrypt
decrypted, err := aead.Open(nil, nonce, ciphertext, additionalData)
if err != nil {
panic(err)
}
fmt.Printf("Decrypted: %s\n", decrypted)
// XChaCha20-Poly1305 with larger nonce
xaead, _ := chacha20poly1305.NewX(key)
xnonce := make([]byte, chacha20poly1305.NonceSizeX)
rand.Read(xnonce)
xciphertext := xaead.Seal(nil, xnonce, plaintext, additionalData)
fmt.Printf("XChaCha20 ciphertext: %x\n", xciphertext)
}ChaCha20 is a stream cipher defined in RFC 8439. This provides the unauthenticated stream cipher; use chacha20poly1305 for authenticated encryption.
const (
KeySize = 32 // Key size in bytes
NonceSize = 12 // Nonce size for ChaCha20
NonceSizeX = 24 // Nonce size for XChaCha20
)// Cipher is a ChaCha20 stream cipher.
type Cipher struct {
// contains unexported fields
}
// NewUnauthenticatedCipher creates a new ChaCha20 or XChaCha20 stream cipher.
// Nonce size determines variant: 12 bytes for ChaCha20, 24 bytes for XChaCha20.
// The initial counter value is set to 0.
func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error)
// SetCounter sets the Cipher counter. The next invocation of XORKeyStream will
// behave as if (counter * 64) bytes had been encrypted so far.
func (s *Cipher) SetCounter(counter uint32)
// XORKeyStream XORs each byte in the given slice with a byte from the cipher's key stream.
func (s *Cipher) XORKeyStream(dst, src []byte)// HChaCha20 generates a derived key for XChaCha20.
// The key must be 32 bytes and nonce must be 16 bytes.
func HChaCha20(key, nonce []byte) ([]byte, error)package main
import (
"crypto/rand"
"fmt"
"golang.org/x/crypto/chacha20"
)
func main() {
key := make([]byte, chacha20.KeySize)
rand.Read(key)
nonce := make([]byte, chacha20.NonceSize)
rand.Read(nonce)
// Create cipher
cipher, err := chacha20.NewUnauthenticatedCipher(key, nonce)
if err != nil {
panic(err)
}
// Encrypt
plaintext := []byte("secret message")
ciphertext := make([]byte, len(plaintext))
cipher.XORKeyStream(ciphertext, plaintext)
fmt.Printf("Ciphertext: %x\n", ciphertext)
// Decrypt (create new cipher with same key/nonce)
cipher2, _ := chacha20.NewUnauthenticatedCipher(key, nonce)
decrypted := make([]byte, len(ciphertext))
cipher2.XORKeyStream(decrypted, ciphertext)
fmt.Printf("Decrypted: %s\n", decrypted)
}Salsa20 is a stream cipher designed by Daniel J. Bernstein.
// XORKeyStream encrypts or decrypts data using Salsa20/20.
// out receives the result, in is the input data.
// nonce must be 8 bytes and key must be 32 bytes.
// The same key/nonce combination must not be reused.
func XORKeyStream(out, in []byte, nonce []byte, key *[32]byte)package main
import (
"crypto/rand"
"fmt"
"golang.org/x/crypto/salsa20"
)
func main() {
var key [32]byte
rand.Read(key[:])
nonce := make([]byte, 8)
rand.Read(nonce)
plaintext := []byte("secret message")
ciphertext := make([]byte, len(plaintext))
// Encrypt
salsa20.XORKeyStream(ciphertext, plaintext, nonce, &key)
fmt.Printf("Ciphertext: %x\n", ciphertext)
// Decrypt
decrypted := make([]byte, len(ciphertext))
salsa20.XORKeyStream(decrypted, ciphertext, nonce, &key)
fmt.Printf("Decrypted: %s\n", decrypted)
}Low-level Salsa family operations. Deprecated - use chacha20poly1305 or salsa20 instead.
var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'}// Core208 applies the Salsa20/8 core function to the 64-byte array in.
func Core208(out *[64]byte, in *[64]byte)
// HSalsa20 applies the HSalsa20 core function to derive a subkey.
func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte)
// XORKeyStream encrypts or decrypts data using Salsa20.
func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte)XTS (XEX-based tweaked-codebook mode with ciphertext stealing) is a cipher mode defined in IEEE P1619/D16, designed for disk encryption.
// Cipher is an XTS cipher.
type Cipher struct {
// contains unexported fields
}
// NewCipher creates a new XTS cipher with the given block cipher and key.
// The key must be twice the block cipher's key size - the first half is used
// for encryption, the second half for tweak generation.
// cipherFunc creates a cipher.Block (e.g., aes.NewCipher).
func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (c *Cipher, err error)
// Encrypt encrypts a sector of data.
// The sector size must be at least 16 bytes and a multiple of the cipher's block size.
// sectorNum is the sector number, used as the tweak.
func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64)
// Decrypt decrypts a sector of data.
// The sector size must be at least 16 bytes and a multiple of the cipher's block size.
// sectorNum is the sector number, used as the tweak.
func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64)package main
import (
"crypto/aes"
"crypto/rand"
"fmt"
"golang.org/x/crypto/xts"
)
func main() {
// XTS requires 2x the key size (32 bytes for AES-128)
key := make([]byte, 32)
rand.Read(key)
// Create XTS cipher
cipher, err := xts.NewCipher(aes.NewCipher, key)
if err != nil {
panic(err)
}
// Encrypt a sector (must be at least 16 bytes)
plaintext := make([]byte, 512) // Typical sector size
copy(plaintext, []byte("secret data"))
ciphertext := make([]byte, len(plaintext))
sectorNum := uint64(0)
cipher.Encrypt(ciphertext, plaintext, sectorNum)
fmt.Printf("Encrypted sector: %x...\n", ciphertext[:32])
// Decrypt
decrypted := make([]byte, len(ciphertext))
cipher.Decrypt(decrypted, ciphertext, sectorNum)
fmt.Printf("Decrypted: %s\n", decrypted[:11])
}The following block ciphers are provided for compatibility with legacy systems only. They should not be used in new applications. Use AES (standard library) or ChaCha20-Poly1305 instead.
Blowfish encryption algorithm. Deprecated - use AES or ChaCha20-Poly1305.
const BlockSize = 8// Cipher is an instance of Blowfish encryption.
type Cipher struct {
// contains unexported fields
}
// NewCipher creates and returns a Cipher.
// The key must be between 1 and 56 bytes.
func NewCipher(key []byte) (*Cipher, error)
// NewSaltedCipher creates a Cipher using the expensive key expansion from bcrypt.
func NewSaltedCipher(key, salt []byte) (*Cipher, error)
func (c *Cipher) BlockSize() int
func (c *Cipher) Encrypt(dst, src []byte)
func (c *Cipher) Decrypt(dst, src []byte)
// KeySizeError reports an invalid key size.
type KeySizeError int
func (k KeySizeError) Error() string// ExpandKey performs key expansion.
func ExpandKey(key []byte, c *Cipher)CAST5 (CAST-128) encryption algorithm (RFC 2144). Deprecated - use AES or ChaCha20-Poly1305.
const BlockSize = 8
const KeySize = 16// Cipher is an instance of CAST5 encryption.
type Cipher struct {
// contains unexported fields
}
// NewCipher creates and returns a new Cipher.
// The key must be 16 bytes.
func NewCipher(key []byte) (c *Cipher, err error)
func (c *Cipher) BlockSize() int
func (c *Cipher) Encrypt(dst, src []byte)
func (c *Cipher) Decrypt(dst, src []byte)TEA (Tiny Encryption Algorithm). Deprecated - use AES or ChaCha20-Poly1305.
const (
BlockSize = 8
KeySize = 16
)// NewCipher creates and returns a cipher.Block.
// The key must be 16 bytes.
func NewCipher(key []byte) (cipher.Block, error)
// NewCipherWithRounds creates a cipher with a custom number of rounds.
// The standard number of rounds is 64.
func NewCipherWithRounds(key []byte, rounds int) (cipher.Block, error)Twofish encryption algorithm. Deprecated - use AES or ChaCha20-Poly1305.
const BlockSize = 16// Cipher is an instance of Twofish encryption.
type Cipher struct {
// contains unexported fields
}
// NewCipher creates and returns a Cipher.
// The key must be 16, 24, or 32 bytes.
func NewCipher(key []byte) (*Cipher, error)
func (c *Cipher) BlockSize() int
func (c *Cipher) Encrypt(dst, src []byte)
func (c *Cipher) Decrypt(dst, src []byte)
// KeySizeError reports an invalid key size.
type KeySizeError int
func (k KeySizeError) Error() stringXTEA (eXtended TEA) encryption algorithm. Deprecated - use AES or ChaCha20-Poly1305.
const BlockSize = 8// Cipher is an instance of XTEA encryption.
type Cipher struct {
// contains unexported fields
}
// NewCipher creates and returns a Cipher.
// The key must be 16 bytes.
func NewCipher(key []byte) (*Cipher, error)
func (c *Cipher) BlockSize() int
func (c *Cipher) Encrypt(dst, src []byte)
func (c *Cipher) Decrypt(dst, src []byte)
// KeySizeError reports an invalid key size.
type KeySizeError int
func (k KeySizeError) Error() stringRecommended for new applications:
Never use without authentication:
Avoid: