// Public DNSSEC snapshots independently signed by Node.js OpenSSL.
// No private signing material is included.

///|
fn main {
  let limits = @dns.Limits::default()
  let time = @dns.TimePolicy::at(150U)
  let zone = @dns.Name::parse("example.").unwrap()
  let anchor = @dns.Dnskey::parse(
    b"\x01\x01\x03\x0f\x26\xcf\xcd\x3b\x19\x35\xd0\x89\x7e\x65\x40\x0d\x1d\xd8\x66\x5b\xc9\x5f\x21\xb7\x63\x74\x9f\xd4\x21\xc1\x2d\x57\xcf\x97\x61\xb7",
  ).unwrap()
  let keyrr = @dns.Record::new(zone, 48, 60U, anchor.rdata()).unwrap()
  let keysig = @dns.Rrsig::parse(
    b"\x00\x30\x0f\x01\x00\x00\x00\x3c\x00\x00\x00\xc8\x00\x00\x00\x64\x93\x47\x07\x65\x78\x61\x6d\x70\x6c\x65\x00\xc7\xa7\x4b\x37\x28\x94\xe1\x1f\x8e\x15\x5e\xe9\x16\x53\x3e\xd2\xa8\x7a\x5e\x99\xda\x50\x29\x4a\xa6\x66\xfb\x57\x0b\x57\x83\x2e\x2e\x67\x1b\x30\xd7\xcb\x64\x32\xef\x7d\x43\x93\xf0\x66\x7c\x8c\xf0\xc9\xc0\x1a\x75\x4e\xe5\xb5\x14\xc7\x51\xa2\xcc\xad\xcc\x08",
  ).unwrap()
  let parent = @dns.anchor_keys(zone, anchor, [keyrr], [keysig], time, limits).unwrap()
  // Resolver workflow: parent DS -> child keys -> signed answer -> cache TTL.
  let child = @dns.Name::parse("child.example.").unwrap()
  let ds = @dns.Record::new(
    child, 43, 60U, b"\x59\x41\x0f\x02\x3e\xf1\x1e\xa3\xa7\x12\x23\x6c\x13\x40\x40\x43\x68\xe4\xc6\x0a\xa9\x34\x95\x7b\xb8\x58\x8c\x68\x3f\x26\x3f\x96\xd1\xae\x61\x59",
  ).unwrap()
  let dssig = @dns.Rrsig::parse(
    b"\x00\x2b\x0f\x02\x00\x00\x00\x3c\x00\x00\x00\xc8\x00\x00\x00\x64\x93\x47\x07\x65\x78\x61\x6d\x70\x6c\x65\x00\x13\xfe\xf8\xee\x66\x58\x49\x79\xf8\x35\x92\xe5\x57\xe5\xc9\x59\x20\x87\xdb\xb9\xdf\x51\x71\xff\x10\x56\x71\x18\xf2\x01\x14\x60\x0e\xef\xba\x73\x81\x32\x2e\xbe\x5e\x08\x1d\x3a\xc0\x90\x20\xbe\x12\x39\x49\x64\x37\x1d\x10\xf0\x91\xa0\x91\xc6\xd1\x60\xa9\x0c",
  ).unwrap()
  let childkey = @dns.Record::new(
    child, 48, 60U, b"\x01\x01\x03\x0f\xce\x7f\x68\x90\x0c\xd8\x86\xbf\x7a\x24\xd4\xe8\xb3\x59\xa3\xb2\xac\x11\x92\xd2\x71\xa3\x20\xc9\x9a\x01\xde\x68\xa8\x25\xf2\x8e",
  ).unwrap()
  let childsig = @dns.Rrsig::parse(
    b"\x00\x30\x0f\x02\x00\x00\x00\x3c\x00\x00\x00\xc8\x00\x00\x00\x64\x59\x41\x05\x63\x68\x69\x6c\x64\x07\x65\x78\x61\x6d\x70\x6c\x65\x00\x20\xbf\x34\x93\xda\x29\xe8\xbd\x72\x9d\x48\x54\xbc\x50\xd4\x0c\x80\x5b\x45\xba\x21\x1b\xdf\x1a\x0d\x18\x7e\x99\xe7\x80\xea\x7f\xa3\x14\xd9\x4f\x0a\x61\x78\x1b\xb6\x81\x66\xc1\x4d\xa6\xe7\x89\x7d\xb6\xf4\x81\x4b\x2d\x44\xee\xc9\xd6\x5c\x2b\xfc\xe9\x78\x05",
  ).unwrap()
  let keys = @dns.delegate_keys(
    parent,
    child,
    [ds],
    [dssig],
    [childkey],
    [childsig],
    time,
    limits,
  ).unwrap()
  let answer = @dns.Record::new(
    @dns.Name::parse("www.child.example.").unwrap(),
    1,
    60U,
    b"\xc0\x00\x02\x02",
  ).unwrap()
  let signature = @dns.Rrsig::parse(
    b"\x00\x01\x0f\x03\x00\x00\x00\x3c\x00\x00\x00\xc8\x00\x00\x00\x64\x59\x41\x05\x63\x68\x69\x6c\x64\x07\x65\x78\x61\x6d\x70\x6c\x65\x00\x61\xa0\xa0\x51\xbf\x27\x09\xd7\x2a\xbb\x7d\x7a\x3c\x0e\xa3\x57\xee\x93\xa5\x14\x1b\xf1\xea\x65\x7c\x3a\xb9\x68\x6f\x4e\xd7\x99\x91\xe2\xd5\xbc\x1c\x04\x4d\x5e\x73\xbf\xd6\xd4\x7d\x12\xbc\xbf\x89\x76\xee\x09\xdd\x57\x7a\x1e\x37\xe0\xfb\xa6\x26\x58\xd6\x00",
  ).unwrap()
  let authenticated = @dns.authenticate_rrset(
    [answer],
    [signature],
    keys,
    time,
    limits,
  ).unwrap()
  println(
    "resolver: signed child answer; cache TTL=" +
    authenticated.cache_records(160U).unwrap()[0].ttl().to_string(),
  )
  // Authoritative tooling workflow: canonical input plus independent signing replay.
  let input = @dns.signing_input([answer], signature, limits).unwrap()
  println(
    "authoritative: canonical signing bytes=" + input.length().to_string(),
  )
  // Offline audit workflow: signed denial snapshots, without trusting parsed records.
  let nsec = @dns.Record::new(
    zone, 47, 60U, b"\x07\x65\x78\x61\x6d\x70\x6c\x65\x00\x00\x07\x22\x00\x00\x00\x00\x03\x80",
  ).unwrap()
  let nsig = @dns.Rrsig::parse(
    b"\x00\x2f\x0f\x01\x00\x00\x00\x3c\x00\x00\x00\xc8\x00\x00\x00\x64\x93\x47\x07\x65\x78\x61\x6d\x70\x6c\x65\x00\x1b\x4c\x23\x67\x6a\x7f\xcb\x1e\xdd\x79\xd0\x10\x09\x3f\x0f\x46\x6c\xfa\x52\x80\xd5\xb0\x49\x91\x2c\xb5\xfc\x2f\xc5\x8c\x2f\x5b\x9e\xba\x48\xac\x43\xab\xab\xa9\x0a\xaf\xe1\x10\x1d\x86\x3c\xa6\x9c\xd4\x79\x0a\x17\x9d\xe4\xc3\x84\x4d\x5c\x99\x5c\xe0\xa8\x03",
  ).unwrap()
  let proof = @dns.authenticate_rrset([nsec], [nsig], parent, time, limits).unwrap()
  let query = @dns.Name::parse("missing.example.").unwrap()
  let denial = @dns.nsec_nxdomain([proof], zone, query, 160U, limits).unwrap()
  println(
    "audit: NSEC NXDOMAIN=" +
    (if denial.verdict() == @dns.Secure { "Secure" } else { "not secure" }),
  )
  let nsec3 = @dns.Record::new(
    @dns.Name::parse("3msev9usmd4br9s97v51r2tdvmr9iqo1.example.").unwrap(),
    50,
    60U,
    b"\x01\x00\x00\x00\x00\x14\x1d\xb8\xef\xa7\xdc\xb3\x48\xbd\xa7\x89\x3f\xca\x1d\x8b\xad\xfd\xb6\x99\x6b\x01\x00\x07\x22\x00\x00\x00\x00\x02\x80",
  ).unwrap()
  let n3sig = @dns.Rrsig::parse(
    b"\x00\x32\x0f\x02\x00\x00\x00\x3c\x00\x00\x00\xc8\x00\x00\x00\x64\x93\x47\x07\x65\x78\x61\x6d\x70\x6c\x65\x00\x4c\xea\x1d\xb7\x3c\xca\xf1\x21\x44\x81\x33\xb9\xdd\x2d\x1f\x84\x72\xac\xfb\x70\x55\xbc\xc9\x7b\x36\xa6\xd0\x33\xf0\x2c\x34\xb1\x75\x01\xeb\x4f\x63\xaa\x1e\xfc\x29\x98\x00\x40\xbf\x47\x14\x2b\x33\x63\xd1\xc9\xdb\x38\x75\x84\x66\x1a\x61\x32\x12\x4c\x33\x01",
  ).unwrap()
  let proof3 = @dns.authenticate_rrset([nsec3], [n3sig], parent, time, limits).unwrap()
  let denial3 = @dns.nsec3_nxdomain([proof3], zone, query, 160U, limits).unwrap()
  println(
    "audit: NSEC3 NXDOMAIN=" +
    (if denial3.verdict() == @dns.Secure { "Secure" } else { "not secure" }),
  )
}