moonzero · control plane v0.15.0 · 49 packages · 4 targets · Apache-2.0 docs / edge / signature GitHub

09 / EDGE

signature

The X-Content-Security request signature: an RSA-sealed envelope carrying the MAC key, the time and the payload type; a MAC over the timestamp, method, path, query and body digest; a tolerance on the timestamp; and an AES-ECB payload when the envelope says the body is sealed.

suberror Refused

itemA content-security failure. Each variant names the one check that refused the request, so a caller can tell a replay from a wrong key.

pub(open) trait Decrypter

itemTurns the sealed secret field of the header into the envelope it carries. Implemented by the RSA decrypter below and open to any transport a caller prefers — an HSM, a KMS, a key in an environment variable.

struct SignatureKey

structOne verification key: the fingerprint a caller names in the header, and the decrypter that opens envelopes sealed for it.

struct SignatureVerifier

structThe verification policy: the keys, how far a timestamp may drift, and whether a request that fails verification is refused or merely ignored.

fn SignatureVerifier::new( keys~ : Array[SignatureKey], tolerance_ms~ : Int64 = 3600000L, strict~ : Bool = false) -> SignatureVerifier

fnA verifier over keys. tolerance_ms defaults to one hour, the expiry SignatureConf carries. A strict verifier refuses a request that fails; a lenient one serves it unsigned, which is how a service rolls the check out before every client signs.

fn SignatureVerifier::strict(self : SignatureVerifier) -> Bool

fnWhether this verifier refuses a request it cannot verify.

fn parse_pairs(value : String) -> Map[String, String]

fnSplit key=value pairs out of a header value: fields separated by ,, name and value by the **first** =, because a base64 value carries padding =. Both sides of a field are trimmed, and a field with no name is skipped.

fn constant_time_eq(a : BytesView, b : BytesView) -> Bool

fnCompare two byte strings without leaking where they differ: a MAC check that returns early lets an attacker count matched octets.

fn parse_i64(text : String) -> Int64?

fnParse a decimal integer, optionally signed. A value that is empty, carries a non-digit, or overflows is None — the caller reports it as a malformed field rather than reading a truncated number.

struct SignatureInput

structA request as the signature check sees it.

struct VerifiedContent

structThe plain content a verified request carries: the HMAC key the envelope named, whether the body was sealed, and the body itself — already decrypted when it was.

fn sign_content( timestamp : String, verb : String, path : String, query : String, body : Bytes) -> Bytes

fnThe MAC preimage: timestamp, method, path, query and the hex SHA-256 of the body, newline separated.

fn verify_signature( verifier : SignatureVerifier, input : SignatureInput, now_ms : Int64) -> VerifiedContent raise Refused

fnVerify one request against verifier at now_ms. On success the returned VerifiedContent carries the body to serve — the plaintext when the request declared an encrypted payload. A failure is the single check that refused it; the caller decides whether that is a 403 or a pass-through, per strict.

fn content_security( verifier : SignatureVerifier, clock : @clock.Clock, header~ : String = "x-content-security") -> Middleware

fnContent-security middleware: verify the X-Content-Security signature on DELETE, GET, POST and PUT requests, the methods the reference implementation checks. A strict verifier answers 403 Forbidden when the check fails. A lenient one serves the request anyway, which is what lets a fleet roll signing out one client at a time. When the envelope declares an encrypted payload, the body served to the application is the decrypted one.