MCPcopy Create free account
hub / github.com/DNSCrypt/encrypted-dns-server / derive

Method derive

src/dnscrypt_certs.rs:49–112  ·  view source on GitHub ↗

Derive the PQ parameters from the classical resolver key seed and the provider signing key, reusing the classical window's serial and dates.

(
        provider_kp: &SignKeyPair,
        resolver_sk_seed: &[u8; 32],
        serial: u32,
        ts_start: u32,
        ts_end: u32,
    )

Source from the content-addressed store, hash-verified

47 /// Derive the PQ parameters from the classical resolver key seed and the
48 /// provider signing key, reusing the classical window's serial and dates.
49 fn derive(
50 provider_kp: &SignKeyPair,
51 resolver_sk_seed: &[u8; 32],
52 serial: u32,
53 ts_start: u32,
54 ts_end: u32,
55 ) -> Self {
56 let mut seed_input = Vec::with_capacity(19 + 32);
57 seed_input.extend_from_slice(b"DNSCrypt-PQ-seed-v1");
58 seed_input.extend_from_slice(resolver_sk_seed);
59 let xwing_seed = pq::sha256(&seed_input);
60 let keypair = pq::XWingKeyPair::from_seed(xwing_seed);
61 let resolver_pk = keypair.public_key_bytes();
62
63 let mut client_magic = [0u8; 8];
64 client_magic.copy_from_slice(&pq::sha256(&resolver_pk)[..8]);
65 if client_magic[..7] == [0u8; 7] || client_magic == pq::PQ_RESUME_MAGIC {
66 client_magic[0] ^= 0xff;
67 }
68
69 let extensions = pq::profile_extension();
70 let serial_be = serial.to_be_bytes();
71 let ts_start_be = ts_start.to_be_bytes();
72 let ts_end_be = ts_end.to_be_bytes();
73
74 let mut signed = Vec::with_capacity(pq::XWING_PK_SIZE + 8 + 4 + 4 + 4 + extensions.len());
75 signed.extend_from_slice(&resolver_pk);
76 signed.extend_from_slice(&client_magic);
77 signed.extend_from_slice(&serial_be);
78 signed.extend_from_slice(&ts_start_be);
79 signed.extend_from_slice(&ts_end_be);
80 signed.extend_from_slice(&extensions);
81 let signature = provider_kp.sk.sign(&signed);
82
83 let mut cert_bytes = Vec::with_capacity(PQ_CERT_LEN);
84 cert_bytes.extend_from_slice(&[0x44, 0x4e, 0x53, 0x43]);
85 cert_bytes.extend_from_slice(&pq::PQ_ES_VERSION);
86 cert_bytes.extend_from_slice(&[0x00, 0x00]);
87 cert_bytes.extend_from_slice(signature.as_bytes());
88 cert_bytes.extend_from_slice(&signed);
89 debug_assert_eq!(cert_bytes.len(), PQ_CERT_LEN);
90
91 // The HKDF context and the extension hash are fixed for the lifetime of
92 // a certificate window, so derive them once here rather than on every
93 // query.
94 let cert_context = pq::cert_context(
95 &pq::PQ_ES_VERSION,
96 &[0x00, 0x00],
97 &resolver_pk,
98 &client_magic,
99 &serial_be,
100 &ts_start_be,
101 &ts_end_be,
102 &extensions,
103 );
104 let profile_extension_hash = pq::sha256(&extensions);
105
106 PqParams {

Callers

nothing calls this directly

Calls 6

sha256Function · 0.85
profile_extensionFunction · 0.85
cert_contextFunction · 0.85
public_key_bytesMethod · 0.80
signMethod · 0.80
as_bytesMethod · 0.45

Tested by

no test coverage detected