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
- Variables
- func DecryptCBC(ciphertext, key, iv []byte) ([]byte, error)
- func EncryptCBC(plaintext, key, iv []byte) ([]byte, error)
- func HKDFExpandSHA256(prk, info []byte, length int) ([]byte, error)
- func HKDFExtractSHA256(salt, ikm []byte) []byte
- func HKDFSHA256(ikm, salt, info []byte, length int) ([]byte, error)
- func HMACSHA256(key, input []byte) []byte
- func OpenGCM(key, nonce, ciphertext, tag, associatedData []byte) (plaintext []byte, err error)
- func SealGCM(key, nonce, plaintext, associatedData []byte) (ciphertext, tag []byte, err error)
- type Aes256Ctr32
Constants ¶
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.
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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.
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.