Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Go runtime/secret - Secure Memory Erasure for Forward Secrecy

The Problem

In cryptographic protocols, sensitive data like ephemeral keys and shared secrets can persist in memory long after they're no longer needed. If an attacker gains access to system memory (through core dumps, memory forensics, or cold boot attacks), they could potentially recover these secrets and compromise forward secrecy.

Traditional approaches to clearing sensitive memory are unreliable:

  • Compiler optimizations may remove "unnecessary" zeroing operations
  • Data may be copied to other memory locations (garbage collector, stack growth)
  • CPU registers may retain sensitive values

The Solution

Go 1.26 introduces the experimental runtime/secret package, which provides a secret.Do(f func()) function that:

  1. Executes your function in a protected context
  2. Automatically erases all temporary storage after completion:
    • CPU registers
    • Stack frames
    • Heap allocations made during execution

This ensures sensitive data cannot be recovered from memory after secret.Do() completes.

Key API

import "runtime/secret"

// Check if currently running in secret mode
secret.Enabled() bool

// Execute function with automatic memory erasure
secret.Do(func() {
    // All memory used here will be erased after this function returns
    privateKey := generateEphemeralKey()
    sharedSecret := computeECDH(privateKey, peerPublic)
    sessionKey = deriveKey(sharedSecret)
    // privateKey and sharedSecret are erased automatically
})

Requirements

This is an experimental feature requiring:

Requirement Value
Go Version 1.26+ (currently development/tip)
Build Flag GOEXPERIMENT=runtimesecret
Platform Linux (amd64/arm64)

Running the Demos

Using Docker (Recommended)

# Build the image (uses golang:tip for Go 1.26+ features)
docker build -t go-runtime-secret .

# Run both demos
docker run --rm go-runtime-secret

# Run individual demos
docker run --rm go-runtime-secret go run simple_demo.go
docker run --rm go-runtime-secret go run crypto_demo.go

Local Development (requires gotip)

# Install Go tip (development version)
go install golang.org/dl/gotip@latest
gotip download

# Run with the experimental flag
GOEXPERIMENT=runtimesecret gotip run simple_demo.go
GOEXPERIMENT=runtimesecret gotip run crypto_demo.go

Demo Files

simple_demo.go - Basic Enabled() Check

Demonstrates the fundamental API by showing secret.Enabled() returns:

  • false outside of secret.Do()
  • true inside of secret.Do()

crypto_demo.go - Ephemeral Key Exchange

Simulates a realistic key exchange scenario:

  1. Ephemeral private key is generated inside secret.Do()
  2. Shared secret is computed (simulated ECDH)
  3. Session key is derived and copied out
  4. All temporaries (private key, shared secret) are automatically erased

Expected Output

simple_demo.go

=== Basic secret.Enabled() Demo ===

Outside secret.Do(): secret.Enabled() = false
Inside secret.Do():  secret.Enabled() = true
After secret.Do():   secret.Enabled() = false

Key insight: When secret.Enabled() returns true, all memory used
during execution will be automatically erased upon exit.

crypto_demo.go

=== Ephemeral Key Exchange with Forward Secrecy ===

Step 1: Entering protected context for key exchange...
        secret.Enabled() = false

Step 2: Inside secret.Do() - all operations are protected
        secret.Enabled() = true

Step 3: Generated ephemeral private key (simulated)
        Key bytes (first 8): a1b2c3d4e5f6a7b8...

Step 4: Computed shared secret with peer (simulated ECDH)
        Shared secret (first 8): 1234abcd5678efgh...

Step 5: Derived session key (this is copied out)
        Session key: <64 hex characters>

Step 6: Exiting secret.Do() - ephemeral key and shared secret
        will be automatically erased from memory!

Step 7: Back in normal context
        secret.Enabled() = false

        The session key is available for use:
        Session key: <64 hex characters>

=== Forward Secrecy Achieved ===

Even if an attacker later gains access to system memory or core dumps,
they cannot recover:
  - The ephemeral private key
  - The shared secret

Only the derived session key remains, and without the ephemeral key,
past sessions cannot be decrypted (forward secrecy).

How It Works

The runtime/secret package modifies Go's runtime behavior when secret.Do() is active:

  1. Stack Management: The runtime tracks all stack frames created during execution and zeros them upon exit
  2. Heap Tracking: Memory allocations made during secret.Do() are tracked and zeroed
  3. Register Clearing: CPU registers are cleared before returning to normal execution
  4. Garbage Collector Integration: The GC is aware of secret mode and handles protected memory appropriately

Use Cases

  • TLS/HTTPS: Protecting ephemeral keys during key exchange
  • Password Handling: Ensuring passwords are erased after validation
  • Cryptographic Operations: Protecting intermediate values in crypto algorithms
  • Secret Key Loading: Safely loading and using encryption keys

References