encrypt

package
v1.150.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 13, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package encrypt provides helpers for encrypting and decrypting data safely for transport and storage.

It solves the problem of protecting application payloads when data moves between systems such as databases, queues, caches, or external services.

This package uses AES-GCM authenticated encryption with a random nonce prefixed to the ciphertext. It provides both raw byte-level APIs and convenience helpers that serialize arbitrary values with gob or JSON before encryption.

Top features:

  • AES-GCM encryption and decryption with standard key sizes (16, 24, or 32 bytes for AES-128, AES-192, and AES-256)
  • nonce generation via secure random bytes and nonce-prefix output format for self-contained ciphertext payloads
  • additional authenticated data (AAD) support via WithAAD to bind contextual data (such as a record ID) into the authentication tag
  • base64 encoded byte and string helpers for transport-safe interchange
  • gob and JSON wrappers for encrypting and decrypting structured Go values
  • layered error propagation from encoding, base64, and cryptographic operations

Benefits:

  • reduce boilerplate for secure payload handling
  • avoid accidental use of insecure or unauthenticated encryption modes
  • simplify encryption of structured data in distributed systems

Security and caveats

  • Random-nonce message limit: each call generates a fresh 96-bit random nonce. With random nonces the number of messages that may safely be encrypted under a single key is bounded by the birthday paradox (see NIST SP 800-38D). Rotate keys well before ~2^32 messages per key to keep the nonce-collision probability negligible. A nonce collision under the same key breaks both confidentiality and authentication.
  • Nonce uniqueness depends entirely on the randomness source. Encrypt uses crypto/rand.Reader. Override it (via EncryptWith and WithRandReader) only in tests; a non-cryptographic or repeating reader causes nonce reuse.
  • The gob helpers (ByteEncryptAny/ByteDecryptAny and their string wrappers) decode with encoding/gob, which is not designed for adversarial input. Because the payload is authenticated before decoding, only data produced by a holder of the key ever reaches the decoder; even so, prefer the JSON family (the *SerializeAny helpers) for cross-language or lower-trust payloads.
  • The Base64 output uses standard encoding (RFC 4648 with '+' and '/'), which is not URL- or filename-safe. Re-encode at the call site if you need to embed the payload in a URL or path.
  • All exported functions are stateless and safe for concurrent use.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrInvalidInputSize = errors.New("encrypt: input shorter than nonce size")

ErrInvalidInputSize is returned by Decrypt and DecryptWith when the payload is shorter than the AES-GCM nonce, so it cannot contain a nonce plus ciphertext.

Functions

func ByteDecryptAny

func ByteDecryptAny(key, msg []byte, data any) error

ByteDecryptAny decrypts Base64 bytes produced by ByteEncryptAny into data.

data must be a pointer to the destination type.

func ByteDecryptSerializeAny

func ByteDecryptSerializeAny(key, msg []byte, data any) error

ByteDecryptSerializeAny decrypts Base64 bytes into JSON-decoded data.

data must be a pointer to the destination type.

func ByteEncryptAny

func ByteEncryptAny(key []byte, data any) ([]byte, error)

ByteEncryptAny gob-encodes data, encrypts it, and returns Base64 bytes.

This helper is useful for encrypting arbitrary Go values for transport.

func ByteEncryptSerializeAny

func ByteEncryptSerializeAny(key []byte, data any) ([]byte, error)

ByteEncryptSerializeAny JSON-encodes data, encrypts it, and returns Base64 bytes.

Use this helper for cross-language payloads where JSON interoperability is required.

func Decrypt

func Decrypt(key, msg []byte) ([]byte, error)

Decrypt opens a nonce-prefixed AES-GCM payload produced by Encrypt.

key must match the key used during encryption.

func DecryptAny

func DecryptAny(key []byte, msg string, data any) error

DecryptAny wraps ByteDecryptAny for string input payloads.

func DecryptSerializeAny

func DecryptSerializeAny(key []byte, msg string, data any) error

DecryptSerializeAny wraps ByteDecryptSerializeAny for string input payloads.

func DecryptWith

func DecryptWith(key, msg []byte, opts ...Option) ([]byte, error)

DecryptWith behaves like Decrypt but accepts options. Only WithAAD is honored: the AAD must match the value passed to EncryptWith or decryption fails. WithRandReader has no effect on decryption.

func Encrypt

func Encrypt(key, msg []byte) ([]byte, error)

Encrypt seals msg with AES-GCM and prepends the random nonce.

key must be 16, 24, or 32 bytes for AES-128/192/256. The output is self-contained: nonce || ciphertext. The nonce is generated from crypto/rand.Reader.

Example

The nonce is random, so the ciphertext differs on every run; these examples print the decrypted round-trip result, which is deterministic and verifiable.

package main

import (
	"fmt"
	"log"

	"github.com/tecnickcom/nurago/pkg/encrypt"
)

func main() {
	key := []byte("abcdefghijklmnopqrstuvwxyz012345") // 32 bytes: AES-256

	enc, err := encrypt.Encrypt(key, []byte("secret message"))
	if err != nil {
		log.Fatal(err)
	}

	dec, err := encrypt.Decrypt(key, enc)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(string(dec))

}
Output:
secret message

func EncryptAny

func EncryptAny(key []byte, data any) (string, error)

EncryptAny wraps ByteEncryptAny and returns a string payload.

func EncryptSerializeAny

func EncryptSerializeAny(key []byte, data any) (string, error)

EncryptSerializeAny wraps ByteEncryptSerializeAny and returns a string payload.

Example
package main

import (
	"fmt"
	"log"

	"github.com/tecnickcom/nurago/pkg/encrypt"
)

func main() {
	type Payload struct {
		Name  string
		Count int
	}

	key := []byte("abcdefghijklmnopqrstuvwxyz012345")

	enc, err := encrypt.EncryptSerializeAny(key, Payload{Name: "widget", Count: 7})
	if err != nil {
		log.Fatal(err)
	}

	var out Payload

	err = encrypt.DecryptSerializeAny(key, enc, &out)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(out.Name, out.Count)

}
Output:
widget 7

func EncryptWith

func EncryptWith(key, msg []byte, opts ...Option) ([]byte, error)

EncryptWith behaves like Encrypt but accepts options that customize the random source used for nonce generation (see WithRandReader) and bind additional authenticated data (see WithAAD).

Without options it is identical to Encrypt and uses crypto/rand.Reader.

Example

ExampleEncryptWith binds additional authenticated data (AAD) to the payload. The same AAD must be supplied when decrypting.

package main

import (
	"fmt"
	"log"

	"github.com/tecnickcom/nurago/pkg/encrypt"
)

func main() {
	key := []byte("abcdefghijklmnopqrstuvwxyz012345")
	aad := []byte("record-id-42")

	enc, err := encrypt.EncryptWith(key, []byte("secret message"), encrypt.WithAAD(aad))
	if err != nil {
		log.Fatal(err)
	}

	dec, err := encrypt.DecryptWith(key, enc, encrypt.WithAAD(aad))
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(string(dec))

}
Output:
secret message

Types

type Option

type Option func(*config)

Option customizes the behavior of EncryptWith and DecryptWith.

Options are additive: existing Encrypt/Decrypt signatures are unchanged and always use the secure default reader (crypto/rand.Reader) with no AAD.

func WithAAD

func WithAAD(aad []byte) Option

WithAAD binds additional authenticated data (AAD) to the ciphertext.

The AAD is authenticated but not encrypted: the exact same value must be supplied to DecryptWith or decryption fails. Use it to bind contextual data (such as a record ID or schema version) to a payload. The high-level Any/Serialize helpers do not expose AAD; use EncryptWith/DecryptWith for it.

func WithRandReader

func WithRandReader(r io.Reader) Option

WithRandReader overrides the random source used to generate the AES-GCM nonce.

SECURITY: the reader MUST be a cryptographically secure source of unique bytes. Reusing a nonce under the same key breaks AES-GCM confidentiality and authentication, so this option is intended for tests only. Production code must use Encrypt (or EncryptWith without this option), which reads from crypto/rand.Reader. It has no effect on DecryptWith.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL