// content_digest_binding — Binding a body via Content-Digest.
///|
fn main {
let body = @utf8.encode("{\"amount\": 100}")
let h = @hsig.OrderedHeaders::new()
let _ = h.append("content-type", "application/json")
let _ = h.append(
"content-digest",
"sha-256=:" + @hsig.base64_encode_bytes(@hsig.sha256_raw(body)) + ":",
)
let req = @hsig.RequestContext::new_default(
"POST",
"https",
"example.com",
"/pay",
None,
h,
Some(body),
).unwrap()
let key : @hsig.KeyRecord = {
keyid: "k1",
algorithm: "hmac-sha256",
material: @hsig.SharedSecret(@utf8.encode("secret")),
}
let params : @hsig.SignatureParameters = {
created: Some(1700000000L),
expires: None,
keyid: Some("k1"),
alg: None,
nonce: None,
tag: None,
extensions: Array::new(),
}
let options : @hsig.SignOptions = {
label: "sig1",
components: [
@hsig.covered_field("content-digest"),
@hsig.covered_field("content-type"),
],
parameters: params,
algorithm: "hmac-sha256",
key,
}
let signed = @hsig.sign_request(req, options, @hsig.Limits::default()).unwrap()
let resolver = @hsig.InMemoryKeyResolver::new()
let _ = resolver.add(key, @hsig.Limits::default())
let clock = @hsig.FixedClock::new(1700000000L)
let nonces = @hsig.InMemoryNonceStore::new()
let policy : @hsig.VerificationPolicy = {
..@hsig.VerificationPolicy::hmac_only(),
require_content_digest: true,
}
let limits = @hsig.Limits::default()
let ok = @hsig.verify_request(
req,
signed.signature_input,
signed.signature,
resolver,
policy,
clock,
nonces,
limits,
@hsig.MultiSignaturePolicy::AnyValid,
)
println(
"correct: " +
(match ok {
Ok(_) => "accepted"
Err(_) => "rejected"
}),
)
let tampered = @hsig.RequestContext::new_default(
"POST",
"https",
"example.com",
"/pay",
None,
h,
Some(@utf8.encode("{\"amount\": 999}")),
).unwrap()
let bad = @hsig.verify_request(
tampered,
signed.signature_input,
signed.signature,
resolver,
policy,
clock,
nonces,
limits,
@hsig.MultiSignaturePolicy::AnyValid,
)
println(
"body modified: " +
(match bad {
Ok(_) => "accepted"
Err(_) => "rejected"
}),
)
}