secure

package
v0.2.5 Latest Latest
Warning

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

Go to latest
Published: Feb 8, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package secure provides memory-safe handling of sensitive data.

This package wraps the memguard library to provide secure storage for secrets in memory. It ensures that sensitive data is:

  • Encrypted at rest in memory (XSalsa20Poly1305)
  • Protected from swapping via mlock
  • Securely wiped when no longer needed
  • Protected from buffer overflow via guard pages

Usage

Create a secure buffer from sensitive bytes:

buf, err := secure.NewSecureBuffer([]byte("my-secret"))
if err != nil {
    // Handle error - may indicate mlock unavailable
}
defer buf.Destroy() // Always destroy when done

// When you need to use the secret:
locked, err := buf.Open()
if err != nil {
    // Handle error
}
defer locked.Destroy() // Destroy the unlocked buffer when done

// Use locked.Bytes() to access the plaintext
secretBytes := locked.Bytes()

Platform Behavior

Memory locking behavior varies by platform:

  • Linux: Requires RLIMIT_MEMLOCK to be set appropriately
  • macOS: Works out of the box
  • Windows: Uses VirtualLock

If mlock is unavailable or fails (e.g., due to RLIMIT_MEMLOCK), memguard handles this gracefully and continues with standard Go memory allocation. Note: memguard may log warnings internally; this package does not add additional logging.

Security Guarantees

This package provides defense-in-depth against memory-based attacks:

  • Core dumps will not contain plaintext secrets
  • Secrets won't be swapped to disk
  • Memory is overwritten with zeros on destruction
  • Guard pages detect buffer overflows

It does NOT protect against:

  • Attackers with root access to the running process
  • Hardware-level attacks (cold boot, DMA)
  • Spectre/Meltdown side-channel attacks

Index

Constants

This section is empty.

Variables

View Source
var ErrBufferDestroyed = errors.New("SecureBuffer has been destroyed")

ErrBufferDestroyed is returned when attempting to use a SecureBuffer after Destroy() was called.

Functions

This section is empty.

Types

type SecureBuffer

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

SecureBuffer provides memory-safe storage for sensitive data. It wraps memguard.Enclave to encrypt secrets at rest in memory and protect them from swapping via mlock.

Note: memguard.Enclave doesn't have a direct Destroy method. Instead, we track the enclave and use memguard.Purge() for cleanup at application exit, or simply let the enclave be garbage collected (the encrypted data is safe even without explicit destruction).

func NewSecureBuffer

func NewSecureBuffer(data []byte) (*SecureBuffer, error)

NewSecureBuffer creates a protected buffer from secret bytes. The input data is immediately copied into a protected memory region and the original data remains unchanged (caller should zero it).

If mlock is unavailable (e.g., due to RLIMIT_MEMLOCK), memguard handles this gracefully and continues with standard memory allocation.

func NewSecureBufferFromString

func NewSecureBufferFromString(s string) (*SecureBuffer, error)

NewSecureBufferFromString creates a SecureBuffer from a string. This is a convenience wrapper for NewSecureBuffer that handles the string-to-bytes conversion.

Note: Go strings are immutable, so the original string cannot be zeroed after this call. For maximum security, prefer working with []byte from the start and avoid string intermediates. However, wrapping in SecureBuffer still provides encrypted storage for subsequent operations.

func (*SecureBuffer) Destroy

func (s *SecureBuffer) Destroy()

Destroy marks this SecureBuffer as destroyed and prevents further use. The underlying encrypted enclave data is safe even without explicit destruction since it's encrypted at rest. However, this method ensures the buffer cannot be accidentally reused.

This method is idempotent - calling it multiple times is safe. After Destroy(), Open() will return ErrBufferDestroyed.

For complete cleanup of all memguard data at application exit, call memguard.Purge() in a defer statement in main().

func (*SecureBuffer) Open

func (s *SecureBuffer) Open() (*memguard.LockedBuffer, error)

Open decrypts and returns the protected data in a locked buffer. The caller MUST call Destroy() on the returned LockedBuffer when done to securely wipe the plaintext from memory.

Example:

locked, err := buf.Open()
if err != nil {
    return err
}
defer locked.Destroy()
secret := locked.Bytes()

Jump to

Keyboard shortcuts

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