Documentation
¶
Overview ¶
Package encryptfs provides a transparent encryption layer for the AbsFs filesystem abstraction, enabling secure at-rest encryption with modern cryptographic primitives.
Overview ¶
encryptfs implements the absfs.FileSystem interface, allowing it to wrap any AbsFs-compatible filesystem and provide transparent encryption and decryption of file contents.
Supported Cipher Suites ¶
Content Encryption:
- AES-256-GCM: Advanced Encryption Standard with 256-bit keys and Galois/Counter Mode for authenticated encryption
- ChaCha20-Poly1305: Modern stream cipher with Poly1305 message authentication
Filename Encryption:
- AES-SIV: Synthetic Initialization Vector mode for deterministic filename encryption (RFC 5297)
Both content cipher suites provide:
- Authenticated Encryption with Associated Data (AEAD)
- Protection against tampering and corruption
- 128-bit authentication tags
- Nonce/IV uniqueness guarantees
Basic Usage ¶
// Create base filesystem
base := osfs.New()
// Create encrypted filesystem with password-based key
config := &encryptfs.Config{
Cipher: encryptfs.CipherAES256GCM,
KeyProvider: encryptfs.NewPasswordKeyProvider(
[]byte("my-secure-password"),
encryptfs.Argon2idParams{
Memory: 64 * 1024, // 64 MB
Iterations: 3,
Parallelism: 4,
},
),
}
fs, err := encryptfs.New(base, config)
if err != nil {
panic(err)
}
// Use like any absfs.FileSystem
file, _ := fs.Create("/secret.txt")
file.WriteString("This will be encrypted on disk")
file.Close()
Filename Encryption ¶
The package supports three modes of filename encryption:
// No filename encryption (content only)
config := &encryptfs.Config{
FilenameEncryption: encryptfs.FilenameEncryptionNone,
}
// Deterministic filename encryption (SIV mode)
config := &encryptfs.Config{
FilenameEncryption: encryptfs.FilenameEncryptionDeterministic,
PreserveExtensions: true, // Keep .txt, .jpg visible
}
// Random filename encryption with metadata database
config := &encryptfs.Config{
FilenameEncryption: encryptfs.FilenameEncryptionRandom,
MetadataPath: "/.encryptfs-metadata.json",
}
Deterministic mode uses AES-SIV to encrypt filenames consistently (same name always produces same ciphertext), preserving directory structure while hiding filenames. Random mode assigns UUID-based names for maximum security.
Security Considerations ¶
Protected Against:
- Unauthorized access to encrypted files at rest
- Data tampering and corruption (authenticated encryption)
- Known-plaintext attacks (with proper key management)
- Offline brute-force attacks (with strong key derivation)
Not Protected Against:
- Memory dumps while files are decrypted in memory
- Side-channel attacks (timing, cache)
- Compromised systems with keyloggers or malware
- Physical access attacks on running systems
- Metadata leakage (file sizes, access patterns - unless filename encryption enabled)
Note: When using FilenameEncryptionDeterministic or FilenameEncryptionRandom, filenames are encrypted, significantly reducing metadata leakage.
Key Derivation ¶
The package supports two key derivation functions:
PBKDF2 (Password-Based Key Derivation Function 2):
- Widely supported and FIPS-approved
- Simple implementation
- CPU-intensive only (vulnerable to GPU attacks)
Argon2id (Recommended):
- Memory-hard function (resistant to GPU/ASIC attacks)
- Winner of Password Hashing Competition
- Configurable memory, time, and parallelism
File Format ¶
Traditional (single-chunk) encrypted files:
- Magic bytes (4 bytes): "ENCR" (0x454E4352)
- Version (1 byte): File format version
- Cipher suite (1 byte): Identifies the encryption algorithm
- Salt size (2 bytes): Length of the salt
- Salt (variable): Random salt for key derivation
- Nonce size (2 bytes): Length of the nonce
- Nonce (variable): Random nonce for encryption
- Ciphertext (variable): Encrypted data + authentication tag
Chunked File Format ¶
For efficient random access, files can be encrypted in chunks (enabled via Config.ChunkSize). Chunked files use this format:
- File Header (same as above)
- Chunk Index (20 KB reserved):
- Chunk size (4 bytes): Size of plaintext chunks
- Chunk count (4 bytes): Number of chunks
- Chunk offsets (8 bytes each): File offset for each chunk
- Plaintext sizes (4 bytes each): Plaintext size for each chunk
- Padding (fills remaining reserved space)
- Encrypted Chunks (variable number):
- Chunk header (plaintext size + nonce)
- Ciphertext (encrypted chunk data + auth tag)
Benefits of chunked format:
- Efficient seeking without decrypting entire file
- Random access to any chunk
- Modify individual chunks without rewriting entire file
- LRU cache reduces disk I/O for frequently accessed chunks
- Each chunk has independent nonce for security
Usage:
config := &encryptfs.Config{
Cipher: encryptfs.CipherAES256GCM,
KeyProvider: keyProvider,
ChunkSize: 64 * 1024, // 64 KB chunks (default)
}
Performance ¶
The implementation uses Go's standard crypto package which includes hardware acceleration (AES-NI) when available. Performance characteristics:
- AES-256-GCM: Typically >2 GB/s with AES-NI
- ChaCha20-Poly1305: Typically >1 GB/s
- Key derivation: Tunable (50-200ms for Argon2id)
Index ¶
- Constants
- Variables
- func CalculateChunkCount(dataSize int64, chunkSize uint32) uint32
- func CalculateCiphertextSize(plaintextSize uint32, nonceSize, tagSize int) int
- func GenerateNonce(cipher CipherSuite) ([]byte, error)
- func HashFuncToHash(hf HashFunc) func() hash.Hash
- func IsAuthenticationError(err error) bool
- func IsCorruptionError(err error) bool
- func IsEncryptionError(err error) bool
- func IsIOError(err error) bool
- func IsValidationError(err error) bool
- func NewAuthenticationError(path string, err error) error
- func NewCorruptionError(path string, message string) error
- func NewDeterministicFilenameEncryptor(key []byte, preserveExtensions bool, separator string) (*deterministicFilenameEncryptor, error)
- func NewEncryptionError(operation, path string, err error) error
- func NewIOError(operation, path string, err error) error
- func NewRandomFilenameEncryptor(key []byte, metadata *FilenameMetadata, separator string) (*randomFilenameEncryptor, error)
- func NewValidationError(field string, value any, message string) error
- func ValidateBuffer(buf []byte, name string, minSize int) error
- func ValidateChunkIndex(index, maxIndex uint32, context string) error
- func ValidateChunkSize(size uint32) error
- func ValidateFilePath(path string) error
- func ValidateKey(key []byte, expectedSize int) error
- func ValidateNonce(nonce []byte, cipher CipherSuite) error
- func ValidateOffset(offset int64, name string) error
- func ValidateReadWrite(buf []byte, position int64) error
- func ValidateSize(size int, name string, minSize, maxSize int) error
- type AESGCMEngine
- type Argon2idParams
- type AuthenticationError
- type ChaCha20Poly1305Engine
- type ChunkHeader
- type ChunkIndexHeader
- func (h *ChunkIndexHeader) ActualSize() int64
- func (h *ChunkIndexHeader) AddChunk(offset uint64, plaintextSize uint32)
- func (h *ChunkIndexHeader) FindChunkForOffset(offset int64) (uint32, int64, error)
- func (h *ChunkIndexHeader) GetChunkInfo(chunkIdx uint32) (offset uint64, plaintextSize uint32, err error)
- func (h *ChunkIndexHeader) ReadFrom(r io.Reader) (int64, error)
- func (h *ChunkIndexHeader) Size() int64
- func (h *ChunkIndexHeader) TotalPlaintextSize() int64
- func (h *ChunkIndexHeader) WriteTo(w io.Writer) (int64, error)
- type ChunkedFile
- func (cf *ChunkedFile) Close() error
- func (cf *ChunkedFile) Name() string
- func (cf *ChunkedFile) Read(p []byte) (int, error)
- func (cf *ChunkedFile) ReadAt(b []byte, off int64) (int, error)
- func (cf *ChunkedFile) ReadBulk(p []byte) (int, error)
- func (cf *ChunkedFile) ReadDir(n int) ([]fs.DirEntry, error)
- func (cf *ChunkedFile) Readdir(n int) ([]os.FileInfo, error)
- func (cf *ChunkedFile) Readdirnames(n int) ([]string, error)
- func (cf *ChunkedFile) Seek(offset int64, whence int) (int64, error)
- func (cf *ChunkedFile) Stat() (os.FileInfo, error)
- func (cf *ChunkedFile) Sync() error
- func (cf *ChunkedFile) Truncate(size int64) error
- func (cf *ChunkedFile) Write(p []byte) (int, error)
- func (cf *ChunkedFile) WriteAt(b []byte, off int64) (int, error)
- func (cf *ChunkedFile) WriteBulk(p []byte) (int, error)
- func (cf *ChunkedFile) WriteString(s string) (int, error)
- type CipherEngine
- type CipherSuite
- type Config
- type CorruptionError
- type EncryptFS
- func (e *EncryptFS) Chdir(dir string) error
- func (e *EncryptFS) Chmod(name string, mode os.FileMode) error
- func (e *EncryptFS) Chown(name string, uid, gid int) error
- func (e *EncryptFS) Chtimes(name string, atime time.Time, mtime time.Time) error
- func (e *EncryptFS) Create(name string) (absfs.File, error)
- func (e *EncryptFS) Getwd() (string, error)
- func (e *EncryptFS) MigrateToNewCipher(root string, newCipher CipherSuite, opts KeyRotationOptions) error
- func (e *EncryptFS) Mkdir(name string, perm os.FileMode) error
- func (e *EncryptFS) MkdirAll(name string, perm os.FileMode) error
- func (e *EncryptFS) Open(name string) (absfs.File, error)
- func (e *EncryptFS) OpenFile(name string, flag int, perm os.FileMode) (absfs.File, error)
- func (e *EncryptFS) ReEncrypt(name string, opts KeyRotationOptions) error
- func (e *EncryptFS) ReadDir(name string) ([]fs.DirEntry, error)
- func (e *EncryptFS) ReadFile(name string) ([]byte, error)
- func (e *EncryptFS) Remove(name string) error
- func (e *EncryptFS) RemoveAll(path string) error
- func (e *EncryptFS) Rename(oldpath, newpath string) error
- func (e *EncryptFS) RotateAllKeys(root string, opts KeyRotationOptions) error
- func (e *EncryptFS) Stat(name string) (os.FileInfo, error)
- func (e *EncryptFS) Sub(dir string) (fs.FS, error)
- func (e *EncryptFS) TempDir() string
- func (e *EncryptFS) Truncate(name string, size int64) error
- func (e *EncryptFS) VerifyAllEncryption(root string) ([]string, error)
- func (e *EncryptFS) VerifyEncryption(name string) error
- func (e *EncryptFS) WalkEncrypted(root string, walkFn EncryptedFileWalker) error
- type EncryptedChunkHeader
- type EncryptedFileWalker
- type EncryptionError
- type EnvKeyProvider
- type FileHeader
- type FilenameEncryption
- type FilenameEncryptor
- type FilenameMetadata
- func (m *FilenameMetadata) Add(encrypted, plaintext string)
- func (m *FilenameMetadata) Get(encrypted string) (string, bool)
- func (m *FilenameMetadata) GetReverse(plaintext string) (string, bool)
- func (m *FilenameMetadata) Load(fs absfs.FileSystem, path string) error
- func (m *FilenameMetadata) Save(fs absfs.FileSystem, path string) error
- type HashFunc
- type IOError
- type KeyProvider
- type KeyRotationOptions
- type MultiKeyProvider
- type PBKDF2Params
- type ParallelConfig
- type PasswordKeyProvider
- type SIVEngine
- type StreamingConfig
- type ValidationError
Constants ¶
const ( // DefaultChunkSize is the default chunk size (64 KB) DefaultChunkSize = 64 * 1024 // MinChunkSize is the minimum allowed chunk size (64 bytes, for testing) MinChunkSize = 64 // MaxChunkSize is the maximum allowed chunk size (16 MB) MaxChunkSize = 16 * 1024 * 1024 // ChunkIndexReservedSize is the reserved space for chunk index (enough for ~1700 chunks) // This prevents the index from overwriting chunk data as it grows // Size calculation: 8 (header) + 1700 * 12 (offset + size per chunk) = 20,408 bytes ChunkIndexReservedSize = 20 * 1024 // 20 KB )
const ( // MagicBytes identifies encrypted files (ASCII: "ENCR") MagicBytes = uint32(0x454E4352) // CurrentVersion is the current file format version CurrentVersion = uint8(1) // HeaderSize is the fixed size of the file header (without salt and nonce) // 4 bytes (magic) + 1 byte (version) + 1 byte (cipher) + 2 bytes (salt size) = 8 bytes MinHeaderSize = 8 )
Variables ¶
var ( ErrInvalidKey = errors.New("invalid encryption key") ErrInvalidCiphertext = errors.New("invalid ciphertext") ErrAuthFailed = errors.New("authentication failed - data may be corrupted or tampered") ErrInvalidHeader = errors.New("invalid file header") ErrUnsupportedVersion = errors.New("unsupported file format version") ErrUnsupportedCipher = errors.New("unsupported cipher suite") ErrNilConfig = errors.New("config cannot be nil") ErrNilKeyProvider = errors.New("key provider cannot be nil") ErrNilBuffer = errors.New("buffer cannot be nil") ErrInvalidOffset = errors.New("invalid file offset") ErrInvalidSize = errors.New("invalid size parameter") ErrNegativeOffset = errors.New("negative offset not allowed") )
Common sentinel errors (kept for backward compatibility)
Functions ¶
func CalculateChunkCount ¶
CalculateChunkCount calculates how many chunks are needed for a given data size
func CalculateCiphertextSize ¶
CalculateCiphertextSize calculates the ciphertext size for a plaintext chunk including the chunk header and authentication tag
func GenerateNonce ¶
func GenerateNonce(cipher CipherSuite) ([]byte, error)
GenerateNonce generates a random nonce for the given cipher
func HashFuncToHash ¶
HashFuncToHash converts HashFunc to hash.Hash
func IsAuthenticationError ¶
IsAuthenticationError checks if an error is an authentication error
func IsCorruptionError ¶
IsCorruptionError checks if an error is a corruption error
func IsEncryptionError ¶
IsEncryptionError checks if an error is an encryption error
func IsValidationError ¶
IsValidationError checks if an error is a validation error
func NewAuthenticationError ¶
NewAuthenticationError creates a new authentication error
func NewCorruptionError ¶
NewCorruptionError creates a new corruption error
func NewDeterministicFilenameEncryptor ¶
func NewDeterministicFilenameEncryptor(key []byte, preserveExtensions bool, separator string) (*deterministicFilenameEncryptor, error)
NewDeterministicFilenameEncryptor creates a new deterministic filename encryptor
func NewEncryptionError ¶
NewEncryptionError creates a new encryption error
func NewIOError ¶
NewIOError creates a new I/O error
func NewRandomFilenameEncryptor ¶
func NewRandomFilenameEncryptor(key []byte, metadata *FilenameMetadata, separator string) (*randomFilenameEncryptor, error)
NewRandomFilenameEncryptor creates a new random filename encryptor
func NewValidationError ¶
NewValidationError creates a new validation error
func ValidateBuffer ¶
ValidateBuffer checks if a buffer is valid (non-nil and has expected size)
func ValidateChunkIndex ¶
ValidateChunkIndex checks if a chunk index is within valid bounds
func ValidateChunkSize ¶
ValidateChunkSize validates that a chunk size is within acceptable bounds
func ValidateFilePath ¶
ValidateFilePath checks if a file path is valid (not empty)
func ValidateKey ¶
ValidateKey checks if a key has the correct size
func ValidateNonce ¶
func ValidateNonce(nonce []byte, cipher CipherSuite) error
ValidateNonce checks if a nonce has the correct size for a cipher
func ValidateOffset ¶
ValidateOffset checks if a file offset is valid
func ValidateReadWrite ¶
ValidateReadWrite checks common preconditions for read/write operations
Types ¶
type AESGCMEngine ¶
type AESGCMEngine struct {
// contains filtered or unexported fields
}
AESGCMEngine implements CipherEngine using AES-256-GCM
func NewAESGCMEngine ¶
func NewAESGCMEngine(key []byte) (*AESGCMEngine, error)
NewAESGCMEngine creates a new AES-256-GCM cipher engine
func (*AESGCMEngine) Decrypt ¶
func (e *AESGCMEngine) Decrypt(nonce, ciphertext []byte) ([]byte, error)
Decrypt decrypts ciphertext using AES-256-GCM
func (*AESGCMEngine) Encrypt ¶
func (e *AESGCMEngine) Encrypt(nonce, plaintext []byte) ([]byte, error)
Encrypt encrypts plaintext using AES-256-GCM
func (*AESGCMEngine) NonceSize ¶
func (e *AESGCMEngine) NonceSize() int
NonceSize returns the nonce size for AES-GCM (12 bytes)
func (*AESGCMEngine) Overhead ¶
func (e *AESGCMEngine) Overhead() int
Overhead returns the authentication tag size (16 bytes)
type Argon2idParams ¶
type Argon2idParams struct {
Memory uint32 // Memory in KiB (e.g., 64*1024 for 64MB)
Iterations uint32 // Number of iterations (time parameter)
Parallelism uint8 // Degree of parallelism
SaltSize int // Salt size in bytes (default 32)
KeySize int // Derived key size in bytes (default 32 for AES-256)
}
Argon2idParams contains parameters for Argon2id key derivation
func (*Argon2idParams) Validate ¶
func (p *Argon2idParams) Validate() error
Validate checks if the Argon2id parameters are valid
type AuthenticationError ¶
type AuthenticationError struct {
Path string // File path
Message string // Human-readable error message
Err error // Underlying error
}
AuthenticationError represents an authentication or authorization failure
func (*AuthenticationError) Error ¶
func (e *AuthenticationError) Error() string
func (*AuthenticationError) Unwrap ¶
func (e *AuthenticationError) Unwrap() error
type ChaCha20Poly1305Engine ¶
type ChaCha20Poly1305Engine struct {
// contains filtered or unexported fields
}
ChaCha20Poly1305Engine implements CipherEngine using ChaCha20-Poly1305
func NewChaCha20Poly1305Engine ¶
func NewChaCha20Poly1305Engine(key []byte) (*ChaCha20Poly1305Engine, error)
NewChaCha20Poly1305Engine creates a new ChaCha20-Poly1305 cipher engine
func (*ChaCha20Poly1305Engine) Decrypt ¶
func (e *ChaCha20Poly1305Engine) Decrypt(nonce, ciphertext []byte) ([]byte, error)
Decrypt decrypts ciphertext using ChaCha20-Poly1305
func (*ChaCha20Poly1305Engine) Encrypt ¶
func (e *ChaCha20Poly1305Engine) Encrypt(nonce, plaintext []byte) ([]byte, error)
Encrypt encrypts plaintext using ChaCha20-Poly1305
func (*ChaCha20Poly1305Engine) NonceSize ¶
func (e *ChaCha20Poly1305Engine) NonceSize() int
NonceSize returns the nonce size for ChaCha20-Poly1305 (12 bytes)
func (*ChaCha20Poly1305Engine) Overhead ¶
func (e *ChaCha20Poly1305Engine) Overhead() int
Overhead returns the authentication tag size (16 bytes)
type ChunkHeader ¶
type ChunkHeader struct {
ChunkSize uint32 // Size of the plaintext chunk
CiphertextSize uint32 // Size of the encrypted chunk (including tag)
Nonce []byte // Nonce for this chunk
}
ChunkHeader represents metadata for an encrypted chunk
type ChunkIndexHeader ¶
type ChunkIndexHeader struct {
ChunkSize uint32 // Size of each plaintext chunk (constant for file)
ChunkCount uint32 // Total number of chunks
ChunkOffsets []uint64 // Byte offset of each chunk from start of file
PlaintextSizes []uint32 // Plaintext size of each chunk (may be < ChunkSize for last chunk)
}
ChunkIndexHeader contains metadata about all chunks in the file
func NewChunkIndexHeader ¶
func NewChunkIndexHeader(chunkSize uint32) *ChunkIndexHeader
NewChunkIndexHeader creates a new chunk index header
func (*ChunkIndexHeader) ActualSize ¶
func (h *ChunkIndexHeader) ActualSize() int64
ActualSize returns the actual size of the data (without padding)
func (*ChunkIndexHeader) AddChunk ¶
func (h *ChunkIndexHeader) AddChunk(offset uint64, plaintextSize uint32)
AddChunk adds a new chunk to the index
func (*ChunkIndexHeader) FindChunkForOffset ¶
func (h *ChunkIndexHeader) FindChunkForOffset(offset int64) (uint32, int64, error)
FindChunkForOffset finds which chunk contains the given plaintext offset Returns: chunk index, offset within chunk, error
func (*ChunkIndexHeader) GetChunkInfo ¶
func (h *ChunkIndexHeader) GetChunkInfo(chunkIdx uint32) (offset uint64, plaintextSize uint32, err error)
GetChunkInfo returns the offset and plaintext size for a given chunk index
func (*ChunkIndexHeader) ReadFrom ¶
func (h *ChunkIndexHeader) ReadFrom(r io.Reader) (int64, error)
ReadFrom reads the chunk index header from a reader
func (*ChunkIndexHeader) Size ¶
func (h *ChunkIndexHeader) Size() int64
Size returns the total size of the chunk index header in bytes (including reserved space)
func (*ChunkIndexHeader) TotalPlaintextSize ¶
func (h *ChunkIndexHeader) TotalPlaintextSize() int64
TotalPlaintextSize returns the total size of all plaintext data
type ChunkedFile ¶
type ChunkedFile struct {
// contains filtered or unexported fields
}
ChunkedFile implements a chunked encrypted file with efficient seeking
func (*ChunkedFile) Read ¶
func (cf *ChunkedFile) Read(p []byte) (int, error)
Read reads up to len(p) bytes from the chunked file
func (*ChunkedFile) ReadAt ¶
func (cf *ChunkedFile) ReadAt(b []byte, off int64) (int, error)
ReadAt reads len(b) bytes from the File starting at byte offset off
func (*ChunkedFile) ReadBulk ¶
func (cf *ChunkedFile) ReadBulk(p []byte) (int, error)
ReadBulk reads data using parallel chunk decryption (experimental) This method is optimized for large sequential reads
func (*ChunkedFile) ReadDir ¶
func (cf *ChunkedFile) ReadDir(n int) ([]fs.DirEntry, error)
ReadDir reads directory entries (not applicable for files)
func (*ChunkedFile) Readdir ¶
func (cf *ChunkedFile) Readdir(n int) ([]os.FileInfo, error)
Readdir reads directory entries (not applicable for files)
func (*ChunkedFile) Readdirnames ¶
func (cf *ChunkedFile) Readdirnames(n int) ([]string, error)
Readdirnames reads directory names (not applicable for files)
func (*ChunkedFile) Seek ¶
func (cf *ChunkedFile) Seek(offset int64, whence int) (int64, error)
Seek sets the offset for the next Read or Write
func (*ChunkedFile) Stat ¶
func (cf *ChunkedFile) Stat() (os.FileInfo, error)
Stat returns file info
func (*ChunkedFile) Sync ¶
func (cf *ChunkedFile) Sync() error
Sync commits the current contents to stable storage
func (*ChunkedFile) Truncate ¶
func (cf *ChunkedFile) Truncate(size int64) error
Truncate changes the size of the file
func (*ChunkedFile) Write ¶
func (cf *ChunkedFile) Write(p []byte) (int, error)
Write writes len(p) bytes to the chunked file
func (*ChunkedFile) WriteAt ¶
func (cf *ChunkedFile) WriteAt(b []byte, off int64) (int, error)
WriteAt writes len(b) bytes to the File starting at byte offset off
func (*ChunkedFile) WriteBulk ¶
func (cf *ChunkedFile) WriteBulk(p []byte) (int, error)
WriteBulk writes data using parallel chunk encryption (experimental) This method is optimized for large sequential writes
func (*ChunkedFile) WriteString ¶
func (cf *ChunkedFile) WriteString(s string) (int, error)
WriteString writes the contents of string s
type CipherEngine ¶
type CipherEngine interface {
// Encrypt encrypts plaintext with the given nonce
Encrypt(nonce, plaintext []byte) ([]byte, error)
// Decrypt decrypts ciphertext with the given nonce
Decrypt(nonce, ciphertext []byte) ([]byte, error)
// NonceSize returns the size of nonces in bytes
NonceSize() int
// Overhead returns the authentication tag size
Overhead() int
}
CipherEngine provides AEAD encryption/decryption
func NewCipherEngine ¶
func NewCipherEngine(cipher CipherSuite, key []byte) (CipherEngine, error)
NewCipherEngine creates a new cipher engine based on the cipher suite
type CipherSuite ¶
type CipherSuite uint8
CipherSuite represents the encryption algorithm to use
const ( // CipherAuto automatically selects the best cipher based on hardware capabilities CipherAuto CipherSuite = iota // CipherAES256GCM uses AES-256 with Galois/Counter Mode CipherAES256GCM // CipherChaCha20Poly1305 uses ChaCha20 stream cipher with Poly1305 MAC CipherChaCha20Poly1305 )
func (CipherSuite) String ¶
func (c CipherSuite) String() string
String returns the string representation of the cipher suite
type Config ¶
type Config struct {
// Cipher suite to use for encryption
Cipher CipherSuite
// KeyProvider supplies encryption keys
KeyProvider KeyProvider
// FilenameEncryption mode (Phase 3 feature)
FilenameEncryption FilenameEncryption
// PreserveExtensions keeps file extensions visible when using filename encryption
PreserveExtensions bool
// MetadataPath is the path to store metadata for random filename encryption
MetadataPath string
// ChunkSize for streaming encryption (Phase 4 feature)
ChunkSize int
// EnableSeek allows seeking within encrypted files (Phase 4 feature)
EnableSeek bool
// Parallel controls parallel chunk processing (Phase 5 feature)
Parallel ParallelConfig
}
Config contains configuration for the encrypted filesystem
type CorruptionError ¶
type CorruptionError struct {
Path string // File path
ChunkIdx uint32 // Chunk index, if applicable
Message string // Human-readable error message
Err error // Underlying error
}
CorruptionError represents a data corruption or integrity check failure
func (*CorruptionError) Error ¶
func (e *CorruptionError) Error() string
func (*CorruptionError) Unwrap ¶
func (e *CorruptionError) Unwrap() error
type EncryptFS ¶
type EncryptFS struct {
// contains filtered or unexported fields
}
EncryptFS implements absfs.FileSystem with transparent encryption
func New ¶
func New(base absfs.FileSystem, config *Config) (*EncryptFS, error)
New creates a new encrypted filesystem wrapping the base filesystem
func (*EncryptFS) Create ¶
Create creates or truncates a file for writing with transparent encryption
func (*EncryptFS) MigrateToNewCipher ¶
func (e *EncryptFS) MigrateToNewCipher(root string, newCipher CipherSuite, opts KeyRotationOptions) error
MigrateToNewCipher migrates all files from one cipher suite to another
func (*EncryptFS) ReEncrypt ¶
func (e *EncryptFS) ReEncrypt(name string, opts KeyRotationOptions) error
ReEncrypt re-encrypts a file with a new key provider
func (*EncryptFS) ReadDir ¶
ReadDir reads the named directory and returns a list of directory entries
func (*EncryptFS) RotateAllKeys ¶
func (e *EncryptFS) RotateAllKeys(root string, opts KeyRotationOptions) error
RotateAllKeys re-encrypts all files in a directory tree with a new key
func (*EncryptFS) VerifyAllEncryption ¶
VerifyAllEncryption verifies all files in a directory can be decrypted
func (*EncryptFS) VerifyEncryption ¶
VerifyEncryption verifies that a file can be decrypted successfully
func (*EncryptFS) WalkEncrypted ¶
func (e *EncryptFS) WalkEncrypted(root string, walkFn EncryptedFileWalker) error
WalkEncrypted walks a directory tree of encrypted files
type EncryptedChunkHeader ¶
type EncryptedChunkHeader struct {
PlaintextSize uint32 // Size of plaintext data in this chunk
Nonce []byte // Nonce for this chunk's encryption
}
EncryptedChunkHeader contains metadata for a single encrypted chunk
func NewEncryptedChunkHeader ¶
func NewEncryptedChunkHeader(plaintextSize uint32, nonce []byte) *EncryptedChunkHeader
NewEncryptedChunkHeader creates a new chunk header
func (*EncryptedChunkHeader) ReadChunkHeader ¶
ReadChunkHeader reads the chunk header from a reader. Note: This method intentionally doesn't implement io.ReaderFrom because it requires the nonceSize parameter which varies by cipher configuration.
func (*EncryptedChunkHeader) Size ¶
func (h *EncryptedChunkHeader) Size() int
Size returns the size of the chunk header in bytes
type EncryptedFileWalker ¶
EncryptedFileWalker is a function type for walking encrypted files
type EncryptionError ¶
type EncryptionError struct {
Operation string // "encrypt" or "decrypt"
Path string // File path, if applicable
ChunkIdx uint32 // Chunk index, if applicable
Message string // Human-readable error message
Err error // Underlying error
}
EncryptionError represents an encryption or decryption failure
func (*EncryptionError) Error ¶
func (e *EncryptionError) Error() string
func (*EncryptionError) Unwrap ¶
func (e *EncryptionError) Unwrap() error
type EnvKeyProvider ¶
type EnvKeyProvider struct {
// contains filtered or unexported fields
}
EnvKeyProvider implements KeyProvider using an environment variable
func NewEnvKeyProvider ¶
func NewEnvKeyProvider(envVar string) *EnvKeyProvider
NewEnvKeyProvider creates a new environment variable key provider
func (*EnvKeyProvider) DeriveKey ¶
func (e *EnvKeyProvider) DeriveKey(salt []byte) ([]byte, error)
DeriveKey returns the key from the environment variable For env-based keys, the salt is ignored as the key is pre-derived
func (*EnvKeyProvider) GenerateSalt ¶
func (e *EnvKeyProvider) GenerateSalt() ([]byte, error)
GenerateSalt generates a new random salt
type FileHeader ¶
type FileHeader struct {
Magic uint32 // Magic bytes to identify encrypted files
Version uint8 // File format version
Cipher CipherSuite // Cipher suite used for encryption
SaltSize uint16 // Size of the salt in bytes
Salt []byte // Salt for key derivation
NonceSize uint16 // Size of the nonce in bytes
Nonce []byte // Nonce/IV for encryption
}
FileHeader represents the header of an encrypted file
func NewFileHeader ¶
func NewFileHeader(cipher CipherSuite, salt, nonce []byte) *FileHeader
NewFileHeader creates a new file header with the given parameters
func (*FileHeader) ReadFrom ¶
func (h *FileHeader) ReadFrom(r io.Reader) (int64, error)
ReadFrom reads the header from the given reader
func (*FileHeader) Size ¶
func (h *FileHeader) Size() int
Size returns the total size of the header in bytes
func (*FileHeader) Validate ¶
func (h *FileHeader) Validate() error
Validate checks if the header is valid
type FilenameEncryption ¶
type FilenameEncryption uint8
FilenameEncryption represents the filename encryption mode
const ( // FilenameEncryptionNone does not encrypt filenames FilenameEncryptionNone FilenameEncryption = iota // FilenameEncryptionDeterministic uses SIV mode for deterministic encryption FilenameEncryptionDeterministic // FilenameEncryptionRandom uses random encryption with metadata database FilenameEncryptionRandom )
type FilenameEncryptor ¶
type FilenameEncryptor interface {
// EncryptFilename encrypts a filename
EncryptFilename(plaintext string) (string, error)
// DecryptFilename decrypts a filename
DecryptFilename(ciphertext string) (string, error)
// EncryptPath encrypts a full path (including directory separators)
EncryptPath(plaintext string) (string, error)
// DecryptPath decrypts a full path
DecryptPath(ciphertext string) (string, error)
}
FilenameEncryptor handles encryption and decryption of filenames
func NewFilenameEncryptor ¶
func NewFilenameEncryptor(config *Config, key []byte, fs absfs.FileSystem) (FilenameEncryptor, error)
NewFilenameEncryptor creates a filename encryptor based on the configuration
type FilenameMetadata ¶
type FilenameMetadata struct {
// Map from encrypted path to plaintext path
Mappings map[string]string `json:"mappings"`
// Map from plaintext path to encrypted path (reverse lookup)
Reverse map[string]string `json:"reverse"`
// contains filtered or unexported fields
}
FilenameMetadata stores mappings between encrypted and plaintext filenames
func NewFilenameMetadata ¶
func NewFilenameMetadata() *FilenameMetadata
NewFilenameMetadata creates a new metadata store
func (*FilenameMetadata) Add ¶
func (m *FilenameMetadata) Add(encrypted, plaintext string)
Add adds a mapping
func (*FilenameMetadata) Get ¶
func (m *FilenameMetadata) Get(encrypted string) (string, bool)
Get retrieves a plaintext filename from an encrypted one
func (*FilenameMetadata) GetReverse ¶
func (m *FilenameMetadata) GetReverse(plaintext string) (string, bool)
GetReverse retrieves an encrypted filename from a plaintext one
func (*FilenameMetadata) Load ¶
func (m *FilenameMetadata) Load(fs absfs.FileSystem, path string) error
Load loads metadata from a file
func (*FilenameMetadata) Save ¶
func (m *FilenameMetadata) Save(fs absfs.FileSystem, path string) error
Save saves metadata to a file
type IOError ¶
type IOError struct {
Operation string // "read", "write", "seek", "open", "close", etc.
Path string // File path
Offset int64 // File offset, if applicable
Message string // Human-readable error message
Err error // Underlying error
}
IOError represents a file system I/O error
type KeyProvider ¶
type KeyProvider interface {
// DeriveKey derives an encryption key from the given salt
DeriveKey(salt []byte) ([]byte, error)
// GenerateSalt generates a new random salt
GenerateSalt() ([]byte, error)
}
KeyProvider is an interface for providing encryption keys
type KeyRotationOptions ¶
type KeyRotationOptions struct {
// NewKeyProvider is the key provider to use for re-encryption
NewKeyProvider KeyProvider
// Cipher suite to use (if different from original)
NewCipher CipherSuite
// PreserveTimestamps keeps original file modification times
PreserveTimestamps bool
// Verbose enables progress output
Verbose bool
// DryRun simulates the operation without making changes
DryRun bool
}
KeyRotationOptions contains options for key rotation operations
type MultiKeyProvider ¶
type MultiKeyProvider struct {
// contains filtered or unexported fields
}
MultiKeyProvider tries multiple key providers in order for decryption This is useful during key rotation/migration
func NewMultiKeyProvider ¶
func NewMultiKeyProvider(providers ...KeyProvider) (*MultiKeyProvider, error)
NewMultiKeyProvider creates a new multi-key provider The first provider is used for new encryptions, others for decryption fallback
func (*MultiKeyProvider) DeriveKey ¶
func (m *MultiKeyProvider) DeriveKey(salt []byte) ([]byte, error)
DeriveKey uses the primary provider
func (*MultiKeyProvider) GenerateSalt ¶
func (m *MultiKeyProvider) GenerateSalt() ([]byte, error)
GenerateSalt uses the primary provider
func (*MultiKeyProvider) TryDeriveKey ¶
func (m *MultiKeyProvider) TryDeriveKey(salt []byte) ([]byte, error)
TryDeriveKey attempts to derive a key using each provider in order Returns the first successful key derivation
type PBKDF2Params ¶
type PBKDF2Params struct {
Iterations int // Number of iterations (minimum 100,000 recommended)
HashFunc HashFunc // Hash function to use
SaltSize int // Salt size in bytes (default 32)
KeySize int // Derived key size in bytes (default 32 for AES-256)
}
PBKDF2Params contains parameters for PBKDF2 key derivation
func (*PBKDF2Params) Validate ¶
func (p *PBKDF2Params) Validate() error
Validate checks if the PBKDF2 parameters are valid
type ParallelConfig ¶
type ParallelConfig struct {
// Enabled enables parallel chunk processing
Enabled bool
// MaxWorkers is the maximum number of worker goroutines
// If 0, defaults to runtime.NumCPU()
MaxWorkers int
// MinChunksForParallel is the minimum number of chunks to use parallel processing
// Below this threshold, sequential processing is used
// Defaults to 4
MinChunksForParallel int
}
ParallelConfig controls parallel chunk processing
func DefaultParallelConfig ¶
func DefaultParallelConfig() ParallelConfig
DefaultParallelConfig returns the default parallel processing configuration
func (*ParallelConfig) Validate ¶
func (p *ParallelConfig) Validate() error
Validate checks if the parallel configuration is valid
type PasswordKeyProvider ¶
type PasswordKeyProvider struct {
// contains filtered or unexported fields
}
PasswordKeyProvider implements KeyProvider using password-based key derivation
func NewPasswordKeyProvider ¶
func NewPasswordKeyProvider(password []byte, params Argon2idParams) *PasswordKeyProvider
NewPasswordKeyProvider creates a new password-based key provider using Argon2id (recommended)
func NewPasswordKeyProviderPBKDF2 ¶
func NewPasswordKeyProviderPBKDF2(password []byte, params PBKDF2Params) *PasswordKeyProvider
NewPasswordKeyProviderPBKDF2 creates a new password-based key provider using PBKDF2
func (*PasswordKeyProvider) DeriveKey ¶
func (p *PasswordKeyProvider) DeriveKey(salt []byte) ([]byte, error)
DeriveKey derives an encryption key from the password and salt
func (*PasswordKeyProvider) GenerateSalt ¶
func (p *PasswordKeyProvider) GenerateSalt() ([]byte, error)
GenerateSalt generates a new random salt
type SIVEngine ¶
type SIVEngine struct {
// contains filtered or unexported fields
}
SIVEngine implements AES-SIV (Synthetic Initialization Vector) mode for deterministic authenticated encryption. This is particularly useful for filename encryption where we need deterministic output.
SIV provides: - Deterministic encryption (same plaintext -> same ciphertext with same key) - Authentication (detects tampering) - Nonce-misuse resistance
Reference: RFC 5297 - Synthetic Initialization Vector (SIV) Authenticated Encryption
func NewSIVEngine ¶
NewSIVEngine creates a new AES-SIV cipher engine Key must be 64 bytes (512 bits) - split into two 32-byte keys
func (*SIVEngine) Decrypt ¶
Decrypt decrypts ciphertext using AES-SIV Additional data (AD) must match what was used during encryption
func (*SIVEngine) Encrypt ¶
Encrypt encrypts plaintext using AES-SIV Additional data (AD) can be provided for authentication
type StreamingConfig ¶
type StreamingConfig struct {
ChunkSize int // Size of each encrypted chunk (default: 64KB)
EnableSeek bool // Allow seeking within encrypted files
}
StreamingConfig controls streaming encryption behavior
func DefaultStreamingConfig ¶
func DefaultStreamingConfig() StreamingConfig
DefaultStreamingConfig returns sensible defaults for streaming
type ValidationError ¶
type ValidationError struct {
Field string // The field or parameter that failed validation
Value any // The invalid value
Message string // Human-readable error message
Err error // Underlying error, if any
}
ValidationError represents a configuration or parameter validation error
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
func (*ValidationError) Unwrap ¶
func (e *ValidationError) Unwrap() error