crypto

package
v1.0.85 Latest Latest
Warning

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

Go to latest
Published: Sep 13, 2025 License: MIT Imports: 21 Imported by: 1

Documentation

Overview

Package crypto implements a **FIPS 140-3 compliant KEM-DEM envelope encryption scheme** suitable for multi-gigabyte streams using ECDH P-256 and AES-256-GCM. This design is Go 1.24+ FIPS compatible (GOFIPS140=v1.0.0) and depends only on standard library crypto packages.

────────────────────────── Design summary ─────────────────────────────

⚙  KEM  (Key-Encapsulation Mechanism)
    • ECDH P-256 + AES-256-GCM for DEK wrapping
    • Output: variable-size encrypted DEK (48-byte DEK + 16-byte GCM tag + ephemeral pubkey)
    • Provides forward secrecy for each blob

⚙  DEM  (Data-Encapsulation Mechanism)
    • AES-256-GCM in ~64 KiB framed chunks (65519 bytes max)
    • Nonce = 4-byte random prefix ∥ 8-byte little-endian counter
    • First frame authenticates header via associated data (prevents tampering)
    • Constant ~64 KiB RAM, O(1) header re-wrap for key rotation

⚙  Fleet key
    • Single ECDSA P-256 key-pair per customer
    • Public key used directly for ECDH operations
    • Private key stored in cloud secret store and fetched at boot

File layout
 ┌─────────────────────────────────────────────────────────────────────────┐
 │ uint16 wrappedLen │ 125B wrapped DEK │ 12B base nonce │ frames... │
 └─────────────────────────────────────────────────────────────────────────┘
                             ▲                    ▲
                             │                    └─ AES-256-GCM frames
                             └─ ECDH + AES-GCM wrapped DEK

Security properties
• Confidentiality & integrity: AES-256-GCM per frame
• Header authentication: first frame includes header as associated data
• Forward-secrecy per object: new ephemeral ECDH key each encryption
• Key rotation: requires re-wrapping only the ~139-byte header
• FIPS 140-3 compliant: uses only approved algorithms

Typical workflow
────────────────
  Publisher:
    1) generate DEK, encrypt stream → dst
    2) ephemeral ECDH + AES-GCM wrap DEK with fleet public key
    3) write header {len, wrapped DEK, nonce} - ~139 bytes total
    4) first frame includes header as associated data for authentication

  Machine node:
    1) read header, unwrap DEK with fleet private key via ECDH
    2) stream-decrypt frames on the fly (first frame verifies header)

Public API ──────────

EncryptFIPSKEMDEMStream(pub *ecdsa.PublicKey, r io.Reader, w io.Writer)
DecryptFIPSKEMDEMStream(priv *ecdsa.PrivateKey, r io.Reader, w io.Writer)

Both return the number of plaintext bytes processed and ensure that every error path is authenticated-failure-safe.

Index

Constants

View Source
const MaxChunkSize = 10 * 1024 * 1024 // 10 MiB

MaxChunkSize is the maximum allowed ciphertext chunk length (bytes).

Variables

View Source
var ErrChunkSizeTooLarge = errors.New("chunk size too large")

ErrChunkSizeTooLarge is returned when a chunk size exceeds the maximum allowed size.

Functions

func CompleteHTTPRequestSignature added in v1.0.85

func CompleteHTTPRequestSignature(key *ecdsa.PrivateKey, req *http.Request, ctx *SignatureContext, resp *http.Response) error

CompleteHTTPRequestSignature completes the signature after the request body has been streamed. This should be called after the body has been fully read (e.g., in an HTTP transport's response handler). The signature is set as an HTTP trailer.

func CompleteHTTPRequestSignatureToWriter added in v1.0.85

func CompleteHTTPRequestSignatureToWriter(key *ecdsa.PrivateKey, req *http.Request, ctx *SignatureContext, w http.ResponseWriter) error

CompleteHTTPRequestSignatureToWriter completes the signature and writes it directly to a ResponseWriter. This is for use in HTTP handlers where you have access to the ResponseWriter.

func DecryptBytes added in v1.0.81

func DecryptBytes(encryptedData []byte, key string) ([]byte, error)

DecryptBytes decrypts a byte array and returns the decrypted bytes. For better performance with large data or when you have readers/writers available, use DecryptStream instead.

func DecryptFIPSKEMDEMStream added in v1.0.74

func DecryptFIPSKEMDEMStream(priv *ecdsa.PrivateKey, src io.Reader, dst io.Writer) (int64, error)

DecryptFIPSKEMDEMStream reverses EncryptFIPSKEMDEMStream using FIPS-approved algorithms.

func DecryptStream added in v1.0.13

func DecryptStream(reader io.Reader, writer io.WriteCloser, key string) error

DecryptStream decrypts data from a reader (like an HTTP response body) using a chunked approach where each chunk has its own nonce and authentication tag. This is secure for large files and streaming data sources. The format of each chunk is: [4-byte chunk size (little-endian)][nonce][encrypted data][tag]

func EncryptBytes added in v1.0.81

func EncryptBytes(data []byte, key string) ([]byte, error)

EncryptBytes encrypts a byte array and returns the encrypted bytes. For better performance with large data or when you have readers/writers available, use EncryptStream instead.

func EncryptFIPSKEMDEMStream added in v1.0.74

func EncryptFIPSKEMDEMStream(pub *ecdsa.PublicKey, src io.Reader, dst io.Writer) (int64, error)

EncryptFIPSKEMDEMStream copies src → dst using FIPS-approved algorithms, returns plaintext bytes written.

func EncryptStream added in v1.0.13

func EncryptStream(reader io.Reader, writer io.WriteCloser, key string) error

EncryptStream encrypts data from a reader using a chunked approach where each chunk has its own nonce and authentication tag. This is secure for large files and streaming data sources. The format of each chunk is: [4-byte chunk size (little-endian)][nonce][encrypted data][tag]

func SignHTTPRequest added in v1.0.73

func SignHTTPRequest(key *ecdsa.PrivateKey, req *http.Request, body []byte) error

func VerifyHTTPRequest added in v1.0.73

func VerifyHTTPRequest(key *ecdsa.PublicKey, req *http.Request, body []byte, checkNonce func(string) error) error

func VerifyHTTPRequestStreaming added in v1.0.85

func VerifyHTTPRequestStreaming(key *ecdsa.PublicKey, req *http.Request, bodyReader io.Reader, checkNonce func(string) error) error

func VerifyHTTPResponseSignature added in v1.0.85

func VerifyHTTPResponseSignature(key *ecdsa.PublicKey, req *http.Request, resp *http.Response, ctx *SignatureContext, checkNonce func(string) error) error

VerifyHTTPResponseSignature verifies a signature that was sent via HTTP trailers (for streaming requests)

func VerifyHTTPResponseSignatureWithBody added in v1.0.85

func VerifyHTTPResponseSignatureWithBody(key *ecdsa.PublicKey, req *http.Request, resp *http.Response, bodyReader io.Reader, timestamp time.Time, nonce string, checkNonce func(string) error) error

VerifyHTTPResponseSignatureWithBody verifies a signature from HTTP trailers without requiring SignatureContext. This allows verification to be decoupled from signing by reading and hashing the body on the verifier side.

Types

type SignatureContext added in v1.0.85

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

SignatureContext holds the state needed to complete a signature after streaming

func PrepareHTTPRequestForStreaming added in v1.0.85

func PrepareHTTPRequestForStreaming(key *ecdsa.PrivateKey, req *http.Request) (*SignatureContext, error)

PrepareHTTPRequestForStreaming sets up a request for streaming signature. Returns a SignatureContext that should be used to complete the signature after the body is streamed.

Jump to

Keyboard shortcuts

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