// 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" }),
)
}