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
- Variables
- func CompleteHTTPRequestSignature(key *ecdsa.PrivateKey, req *http.Request, ctx *SignatureContext, ...) error
- func CompleteHTTPRequestSignatureToWriter(key *ecdsa.PrivateKey, req *http.Request, ctx *SignatureContext, ...) error
- func DecryptBytes(encryptedData []byte, key string) ([]byte, error)
- func DecryptFIPSKEMDEMStream(priv *ecdsa.PrivateKey, src io.Reader, dst io.Writer) (int64, error)
- func DecryptStream(reader io.Reader, writer io.WriteCloser, key string) error
- func EncryptBytes(data []byte, key string) ([]byte, error)
- func EncryptFIPSKEMDEMStream(pub *ecdsa.PublicKey, src io.Reader, dst io.Writer) (int64, error)
- func EncryptStream(reader io.Reader, writer io.WriteCloser, key string) error
- func SignHTTPRequest(key *ecdsa.PrivateKey, req *http.Request, body []byte) error
- func VerifyHTTPRequest(key *ecdsa.PublicKey, req *http.Request, body []byte, ...) error
- func VerifyHTTPRequestStreaming(key *ecdsa.PublicKey, req *http.Request, bodyReader io.Reader, ...) error
- func VerifyHTTPResponseSignature(key *ecdsa.PublicKey, req *http.Request, resp *http.Response, ...) error
- func VerifyHTTPResponseSignatureWithBody(key *ecdsa.PublicKey, req *http.Request, resp *http.Response, ...) error
- type SignatureContext
Constants ¶
const MaxChunkSize = 10 * 1024 * 1024 // 10 MiB
MaxChunkSize is the maximum allowed ciphertext chunk length (bytes).
Variables ¶
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
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
DecryptFIPSKEMDEMStream reverses EncryptFIPSKEMDEMStream using FIPS-approved algorithms.
func DecryptStream ¶ added in v1.0.13
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
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
EncryptFIPSKEMDEMStream copies src → dst using FIPS-approved algorithms, returns plaintext bytes written.
func EncryptStream ¶ added in v1.0.13
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 VerifyHTTPRequest ¶ added in v1.0.73
func VerifyHTTPRequestStreaming ¶ added in v1.0.85
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.