// sign_response — Sign a response including its related request via `req`.

///|
fn main {
  let rh = @hsig.OrderedHeaders::new()
  let _ = rh.append("content-type", "application/json")
  let related = @hsig.RequestContext::new_default(
    "POST",
    "https",
    "example.com",
    "/order",
    None,
    rh,
    None,
  ).unwrap()
  let response = @hsig.ResponseContext::new_default(
    201,
    rh,
    None,
    Some(related),
  ).unwrap()
  let key : @hsig.KeyRecord = {
    keyid: "server-key",
    algorithm: "hmac-sha256",
    material: @hsig.SharedSecret(@utf8.encode("server-secret")),
  }
  let req_method = @hsig.covered_derived_with_params(
    @hsig.DerivedComponent::Method,
    { sf: false, key: None, bs: false, tr: false, req: true, name: None },
  )
  let params : @hsig.SignatureParameters = {
    created: Some(1700000000L),
    expires: None,
    keyid: Some("server-key"),
    alg: None,
    nonce: None,
    tag: None,
    extensions: Array::new(),
  }
  let options : @hsig.SignOptions = {
    label: "respsig",
    components: [
      @hsig.covered_derived(@hsig.DerivedComponent::Status),
      req_method,
    ],
    parameters: params,
    algorithm: "hmac-sha256",
    key,
  }
  let signed = @hsig.sign_response(response, options, @hsig.Limits::default()).unwrap()
  println(signed.signature_base.text)
  // Tamper with the status: 201 -> 500.
  let tampered = @hsig.ResponseContext::new_default(
    500,
    rh,
    None,
    response.related_request,
  ).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 result = @hsig.verify_response(
    tampered,
    signed.signature_input,
    signed.signature,
    resolver,
    @hsig.VerificationPolicy::hmac_only(),
    clock,
    nonces,
    @hsig.Limits::default(),
    @hsig.MultiSignaturePolicy::AnyValid,
  )
  println(
    "tampered status: " +
    (match result {
      Ok(_) => "accepted"
      Err(_) => "rejected"
    }),
  )
}