crypto

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 14, 2026 License: AGPL-3.0 Imports: 9 Imported by: 0

Documentation

Overview

Package crypto provides thin, allocation-conscious wrappers over the Go standard library's symmetric primitives, with an error taxonomy and semantics mirroring upstream signalapp/libsignal (rust/crypto and rust/protocol/src/crypto.rs). These are internal building blocks for the Signal protocol; they are not part of the module's public API.

The package name intentionally matches the import path mandated by the implementation plan (internal/crypto). Being import-restricted to this module, the stdlib-name shadowing that revive warns about cannot affect external callers (see the scoped exclusion in .golangci.yml).

Index

Constants

View Source
const (
	// NonceSizeGCM is the standard 96-bit GCM nonce length.
	NonceSizeGCM = 12
	// TagSizeGCM is the GCM authentication tag length in bytes.
	TagSizeGCM = 16
)

AES-256-GCM parameters, matching rust/crypto/src/aes_gcm.rs.

View Source
const NonceSizeCTR = blockSize - 4 // 12

NonceSizeCTR is the AES-256-CTR nonce size used by Signal: 12 bytes, leaving the trailing 4 bytes of the AES block as a 32-bit big-endian counter (rust/crypto/src/aes_ctr.rs: NONCE_SIZE = BlockSize - 4).

Variables

View Source
var (
	// ErrInvalidKeySize is returned when a key is not the expected length.
	ErrInvalidKeySize = errors.New("crypto: invalid key size")
	// ErrInvalidNonceSize is returned when a nonce/IV is not the expected length.
	ErrInvalidNonceSize = errors.New("crypto: invalid nonce size")
	// ErrInvalidTag is returned when an AES-GCM authentication tag is the wrong
	// length or fails verification.
	ErrInvalidTag = errors.New("crypto: invalid authentication tag")
	// ErrBadCiphertext is returned when ciphertext is malformed (e.g. wrong
	// length or invalid padding). It intentionally does not distinguish the
	// specific failure mode.
	ErrBadCiphertext = errors.New("crypto: bad ciphertext")
)

Sentinel errors returned by this package. They are wrapped with %w so callers can match them with errors.Is.

The taxonomy mirrors rust/crypto/src/error.rs and the per-module error enums: CBC distinguishes a bad key/IV from corrupt ciphertext; CTR/GCM distinguish bad key size, bad nonce size, and (for GCM) tag mismatch. Padding/MAC failures are deliberately reported as a single "bad ciphertext" condition because, per the upstream comment, message corruption can manifest as either and the cases must not be distinguishable to an attacker.

Functions

func DecryptCBC

func DecryptCBC(ciphertext, key, iv []byte) ([]byte, error)

DecryptCBC decrypts AES-256-CBC + PKCS#7 ciphertext, mirroring rust/crypto/src/aes_cbc.rs aes_256_cbc_decrypt. The ciphertext length must be a non-zero multiple of the block size. Padding failures are reported as ErrBadCiphertext and are intentionally indistinguishable from other corruption (see errors.go).

func EncryptCBC

func EncryptCBC(plaintext, key, iv []byte) ([]byte, error)

EncryptCBC encrypts plaintext with AES-256-CBC and PKCS#7 padding, mirroring rust/crypto/src/aes_cbc.rs aes_256_cbc_encrypt. The key must be 32 bytes and the IV 16 bytes; otherwise ErrInvalidKeySize / ErrInvalidNonceSize is returned.

func HKDFExpandSHA256

func HKDFExpandSHA256(prk, info []byte, length int) ([]byte, error)

HKDFExpandSHA256 performs the HKDF-Expand step (RFC 5869 §2.3) with SHA-256, deriving length bytes of output keying material from a pseudorandom key and info string. It returns an error if length exceeds 255*HashLen (8160 bytes).

func HKDFExtractSHA256

func HKDFExtractSHA256(salt, ikm []byte) []byte

HKDFExtractSHA256 performs the HKDF-Extract step (RFC 5869 §2.2) with SHA-256, returning the 32-byte pseudorandom key. A nil/empty salt is treated as a string of HashLen zero bytes, per the RFC.

crypto/hkdf.Extract reports an error only when the supplied hash constructor is unusable; SHA-256 always is, so this never fails and returns no error.

func HKDFSHA256

func HKDFSHA256(ikm, salt, info []byte, length int) ([]byte, error)

HKDFSHA256 is the one-shot HKDF (Extract then Expand) with SHA-256, deriving length bytes from input keying material, salt, and info. It returns an error if length exceeds 255*HashLen (8160 bytes).

func HMACSHA256

func HMACSHA256(key, input []byte) []byte

HMACSHA256 computes HMAC-SHA256 over input with the given key, mirroring rust/protocol/src/crypto.rs hmac_sha256. HMAC accepts a key of any length, so this never fails; the result is always 32 bytes.

func OpenGCM

func OpenGCM(key, nonce, ciphertext, tag, associatedData []byte) (plaintext []byte, err error)

OpenGCM verifies the tag and decrypts AES-256-GCM ciphertext. A wrong key, nonce, tag, ciphertext, or associated data yields ErrInvalidTag (GCM does not distinguish these). The key must be 32 bytes, the nonce 12 bytes, and the tag 16 bytes.

func SealGCM

func SealGCM(key, nonce, plaintext, associatedData []byte) (ciphertext, tag []byte, err error)

SealGCM encrypts plaintext with AES-256-GCM and returns the ciphertext and authentication tag separately (the Rust API computes the tag separately, so callers control framing). The key must be 32 bytes and the nonce 12 bytes.

Types

type Aes256Ctr32

type Aes256Ctr32 struct {
	// contains filtered or unexported fields
}

Aes256Ctr32 is AES-256 in counter mode with a 12-byte nonce and a 32-bit big-endian block counter, matching rust/crypto/src/aes_ctr.rs Aes256Ctr32.

Unlike the standard library's CTR (which treats the whole 16-byte IV as a 128-bit counter), only the trailing 32 bits increment; the 12-byte nonce prefix is fixed. The two agree until the 32-bit counter would overflow into the nonce, which for Signal's message sizes never happens, but we implement the 32-bit behavior to remain faithful to the upstream contract.

func NewAES256CTR32

func NewAES256CTR32(key, nonce []byte, initCtr uint32) (*Aes256Ctr32, error)

NewAES256CTR32 constructs a CTR stream for the given 32-byte key and 12-byte nonce, starting at block counter initCtr. It returns ErrInvalidKeySize or ErrInvalidNonceSize on bad input lengths.

func (*Aes256Ctr32) Process

func (c *Aes256Ctr32) Process(buf []byte)

Process XORs the AES-CTR keystream into buf in place (encrypt and decrypt are the same operation). It may be called repeatedly to process a stream; the counter advances across calls.

Directories

Path Synopsis
Package gcmsiv implements AES-256-GCM-SIV, the nonce-misuse-resistant AEAD of RFC 8452.
Package gcmsiv implements AES-256-GCM-SIV, the nonce-misuse-resistant AEAD of RFC 8452.

Jump to

Keyboard shortcuts

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