QueryParam
struct QueryParamOne query parameter, unencoded. Signing encodes it.
Implements Copyable, Movable
- Fields
name: Stringvalue: String
objectstore.sigv4objectstore.sigv4 — AWS Signature Version 4, header and query flavours.
Split out of s3 because it is pure string algebra over crypto: given a
method, a path, query parameters, headers and a payload hash it produces the
canonical request, the string to sign, and the signature. That shape is what
makes it testable against the published aws-sig-v4-test-suite vectors
without a network or an S3 server anywhere in the picture.
Two callers use it: S3Client, which signs with an Authorization header,
and presign_url, which moves the same material into the query string so a
URL can be handed to something that knows nothing about AWS.
QueryParamstruct QueryParamOne query parameter, unencoded. Signing encodes it.
Implements Copyable, Movable
name: Stringvalue: StringAmzTimestruct AmzTimeA signing timestamp in the two forms SigV4 needs.
Implements Copyable, Movable
amz_date: String: 20150830T123600Z — the X-Amz-Date header value.date_stamp: String: 20150830 — the date half of the credential scope.from_epochdef from_epoch(epoch: Int) -> Self UTC calendar date from a Unix timestamp.
Days-to-civil from Howard Hinnant's chrono-compatible algorithm: it
shifts the era so that leap days land at the end, which makes the
whole conversion branch-free integer arithmetic. Mojo has no calendar
library, and re-deriving this is cheaper than another FFI call.
nowdef now() -> Self from_amz_datedef from_amz_date(amz_date: String) -> Self Reuses an X-Amz-Date value the caller already has (the test vectors, or a retried request that must keep its timestamp).
SignedRequeststruct SignedRequestEverything a signing pass produced, so tests can check each stage.
Implements Copyable, Movable
canonical_request: Stringstring_to_sign: Stringsignature: Stringsigned_headers: Stringauthorization: Stringepoch_nowdef epoch_now() -> Int Seconds since the Unix epoch, via the FFI shim.
Mojo's std.time offers only a monotonic clock, and SigV4 needs a real
UTC timestamp — AWS rejects requests more than 15 minutes out of skew.
canonical_pathdef canonical_path(path: String, normalize: Bool = False) -> String The canonical URI: each segment percent-encoded once, / left alone.
normalize collapses ./.. and duplicate slashes, which is what every
AWS service except S3 wants. S3 signs the un-normalized path — an S3
key may legitimately contain a literal .. segment — so the S3 client
leaves this off.
canonical_querydef canonical_query(params: List[QueryParam]) -> String Encoded k=v pairs sorted by encoded name, then encoded value.
canonical_headersdef canonical_headers(headers: List[Header]) -> Tuple[String, String] Returns (canonical header block, signed header list).
Names are lowercased and sorted; repeated names are joined with commas in the order they appeared, per the SigV4 spec.
canonical_requestdef canonical_request(method: String, path: String, params: List[QueryParam], headers: List[Header], payload_hash: String, normalize: Bool = False) -> Tuple[String, String] Returns (canonical request, signed headers).
credential_scopedef credential_scope(date_stamp: String, region: String, service: String) -> String string_to_signdef string_to_sign(amz_date: String, scope: String, canonical_req: String) -> String signing_keydef signing_key(secret_key: String, date_stamp: String, region: String, service: String) -> List[UInt8] The four-step HMAC ladder: date, region, service, aws4_request.
signdef sign(secret_key: String, date_stamp: String, region: String, service: String, to_sign: String) -> String sign_requestdef sign_request(method: String, path: String, params: List[QueryParam], headers: List[Header], payload_hash: String, access_key: String, secret_key: String, region: String, service: String, when: AmzTime, normalize: Bool = False) -> SignedRequest Header-flavoured SigV4.
headers must already contain host, x-amz-date and, when a session
token is in play, x-amz-security-token: which headers are signed is the
caller's decision, and S3 in particular insists that
x-amz-content-sha256 be among them.
presign_querydef presign_query(method: String, path: String, params: List[QueryParam], headers: List[Header], access_key: String, secret_key: String, session_token: String, region: String, service: String, when: AmzTime, expires_seconds: Int, normalize: Bool = False) -> String Query-flavoured SigV4: returns the full canonical query string, X-Amz-Signature included.
The payload hash for a presigned URL is UNSIGNED-PAYLOAD: the point of
presigning is that whoever follows the URL never sees the credentials, so
they cannot be expected to hash a body the signer never had.
comptime ALGORITHM = String("AWS4-HMAC-SHA256")comptime UNSIGNED_PAYLOAD = String("UNSIGNED-PAYLOAD")comptime EMPTY_SHA256 = String("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")SHA-256 of the empty string — the payload hash of every bodyless request.