doublecrypt

package
v0.0.0-...-c16d419 Latest Latest
Warning

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

Go to latest
Published: Jun 14, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package doublecrypt implements the HXC-1361 double-encryption data path for Helix Cluster OS: WireGuard L3 (injected dependency) + mTLS L7 (real, in this package via crypto/tls and crypto/x509 from the Go standard library only).

Architecture

The design follows the §11.4 two-layer envelope:

┌─────────────────────────────────────────────────┐
│  L7  mTLS (real — crypto/tls TLS 1.3, ECDSA)   │
│  implemented here; wraps any net.Conn            │
├─────────────────────────────────────────────────┤
│  L3  WireGuard (injected dependency)             │
│  DialWireGuard returns ErrUnsupported when no    │
│  WG device is present; never fabricates a conn  │
└─────────────────────────────────────────────────┘

In production the caller:

  1. Obtains a *net.Conn from the WG tunnel (L3), then
  2. Wraps it with ClientConn / ServerConn to add L7 mTLS.

In tests net.Pipe() is passed as the inner conn so that the mTLS handshake and data transfer are exercised fully without requiring a real WG device.

CLAUDE-2 compliance

Where a genuine OS or environment capability is absent (WireGuard kernel device / wireguard-go user-space not configured), DialWireGuard returns the typed ErrUnsupported sentinel and a nil conn. It MUST NOT fabricate a connection or return nil error for a missing capability.

Index

Constants

This section is empty.

Variables

View Source
var ErrUnsupported = errors.New("doublecrypt: WireGuard L3 dialer unsupported in this environment")

ErrUnsupported is returned by DialWireGuard when no WireGuard device (kernel or wireguard-go user-space) is available in the current environment. Callers must check with errors.Is(err, ErrUnsupported) and either inject a pre-dialed conn or abort cleanly.

CLAUDE-2 rationale: fabricating a conn would be a PASS-bluff (§7.1) for a feature that claims real L3 WireGuard encryption.

Functions

func ClientConn

func ClientConn(inner net.Conn, cfg *tls.Config) *tls.Conn

ClientConn wraps inner with TLS as a client using cfg. In the double-encryption stack, inner is the WireGuard L3 net.Conn; in tests it is one end of a net.Pipe().

The caller must call Handshake() (or perform a read/write which triggers it) before exchanging application data.

func DialWireGuard

func DialWireGuard(_ context.Context, _ string) (net.Conn, error)

DialWireGuard represents the L3 WireGuard dialer for the double-encryption stack. It always returns ErrUnsupported because no WireGuard kernel device or wireguard-go user-space process is guaranteed to be present in the sandbox or CI environment.

CLAUDE-2 mandate: where a real OS capability is absent, return a typed ErrUnsupported sentinel and a nil conn. Fabricating a conn is a §7.1 PASS-bluff and is FORBIDDEN.

In production, callers replace this with their WireGuard dialer and pass the resulting net.Conn into ClientConn / ServerConn to add the L7 mTLS layer.

func NewMTLSConfig

func NewMTLSConfig(certPEM, keyPEM, caPEM []byte, isServer bool) (*tls.Config, error)

NewMTLSConfig builds a *tls.Config for mutual TLS over any net.Conn.

Parameters:

  • certPEM PEM-encoded certificate for this endpoint (server or client).
  • keyPEM PEM-encoded private key matching certPEM.
  • caPEM PEM-encoded CA certificate used to verify the peer.
  • isServer true → server-side config (sets ClientCAs + RequireAndVerifyClientCert); false → client-side config (sets RootCAs + Certificates).

The minimum TLS version is TLS 1.3. InsecureSkipVerify is never set.

Returns a non-nil error when:

  • caPEM cannot be parsed or cannot be loaded into the cert pool.
  • certPEM / keyPEM cannot be parsed as a valid key pair.

func ServerConn

func ServerConn(inner net.Conn, cfg *tls.Config) *tls.Conn

ServerConn wraps inner with TLS as a server using cfg. In the double-encryption stack, inner is the WireGuard L3 net.Conn; in tests it is one end of a net.Pipe().

The caller must call Handshake() (or perform a read/write which triggers it) before exchanging application data.

Types

This section is empty.

Jump to

Keyboard shortcuts

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