Hi, Some time ago I started a thread in a DNSSEC mailing list asking about signing a zone in two different locations, and which considerations I should take[1]. My intention was to create identical signed zone in different locations.
Currently OpenDNSSEC can't do that because the inception date depends on the time the data is being signed, and the expiration date depends on a random jitter. So, to ensure the signatures have equal inception/expiration, you need to remove the time/randomness dependencies. I've worked in the following solution using version 1.1.0 - inception doesn't depend on the current time, but in the current hour. That criteria can be changed to round the time to certain unit of time. - expiration still uses a jitter, but is not a uniformly distributed random variable, but a step function that takes as input the RRset label and returns a value between [0, 2*JITTER]. By using this, you make the jitter to depend on the label. Initially I tested using the relative number of the RRset within the zone, but if you provide zones with equal content but different order, the signatures won't be the same. Recently I updated to 1.1.2 and previous patch were not usable directly, so I rewrote and tested. Using two boxes running the same patched version of OpenDNSSEC, with the same KASP, keys and state (files in /var/opendnssec/tmp), from the same input zone we generated the same signed zone in both boxes. The signing process started with a two-minute difference and even one of the signing boxes took double the time to finish the signing. The distribution of the signature expiration date is still good, but not perfect. That depends on the quality of the hash function used to calculate the jitter. I'm attaching a graph with expiration distribution of my test zone. CAVEATS: - the signing process has to start in the same hour. - the current jitter generation behavior is hard-coded, including the unit of time used to round down the inception time. It seems reasonable, if the feature is approved, to make changes to the kasp.xml to signal which mechanism use to generate jitter. TODO - Test with more and bigger zones. My test zone has 50,000 records. I hoping to generate some discussion about the correctness of the solution. The corresponding patches are attached. cheers, [1] http://dnssec-deployment.org/pipermail/dnssec-deployment/2010-February/003653.html -- Sebastian Castro DNS Specialist .nz Registry Services (New Zealand Domain Name Registry Limited) desk: +64 4 495 2337 mobile: +64 21 400535
Index: signer/src/signer/rrset.c
===================================================================
--- signer/src/signer/rrset.c (revision 3778)
+++ signer/src/signer/rrset.c (working copy)
@@ -433,7 +433,7 @@
*/
static void
rrset_sign_set_timers(signconf_type* sc, ldns_rr_type rrtype, time_t signtime,
- time_t* inception, time_t* expiration)
+ double mult, time_t* inception, time_t* expiration)
{
time_t jitter = 0;
time_t offset = 0;
@@ -447,6 +447,7 @@
jitter = duration2time(sc->sig_jitter);
if (jitter) {
random_jitter = se_rand(jitter*2);
+ random_jitter = (time_t)2 * mult * jitter;
}
offset = duration2time(sc->sig_inception_offset);
if (rrtype == LDNS_RR_TYPE_NSEC || rrtype == LDNS_RR_TYPE_NSEC3) {
@@ -523,6 +524,7 @@
key_type* key = NULL;
time_t inception = 0;
time_t expiration = 0;
+ double jitter_mul = 0.0;
se_log_assert(rrset);
se_log_assert(sc);
@@ -541,8 +543,11 @@
"list", rrset->rr_type);
return 1;
}
+ /* XXX Find the owner name for the rr_list */
+ /* XXX Calculate an index based on the owner name */
+ jitter_mul = get_jitter_step(rrset_get_label(rrset));
rrset_sign_set_timers(sc, rrset->rr_type, signtime,
- &inception, &expiration);
+ jitter_mul, &inception, &expiration);
key = sc->keys->first_key;
while (key) {
if ((!key->zsk && rrset->rr_type != LDNS_RR_TYPE_DNSKEY) ||
@@ -693,3 +698,46 @@
}
return;
}
+
+/**
+ * Find the label for a RRset
+ */
+char *
+rrset_get_label(rrset_type* rrset)
+{
+ ldns_dnssec_rrs* rrs = NULL;
+
+ rrs = rrset->rrs;
+ while (rrs) {
+ if (rrs->rr) {
+ return ldns_rdf2str(rrs->rr->_owner);
+ }
+ rrs = rrs->next;
+ }
+
+ return NULL;
+}
+
+unsigned long
+str2hash(char *str)
+{
+ unsigned long hash = 5381;
+ int c;
+
+ while( (c = *str++) )
+ hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
+
+ return hash;
+}
+
+
+double
+get_jitter_step(char *str) {
+ /* First get the hash for the given string */
+ unsigned long hash = str2hash(str);
+ /* Normalize the value to something between [0, 1] */
+ double step = (double)(hash % 503) / 503;
+
+ return step;
+}
+
Index: signer/src/signer/rrset.h
===================================================================
--- signer/src/signer/rrset.h (revision 3778)
+++ signer/src/signer/rrset.h (working copy)
@@ -153,4 +153,7 @@
*/
void rrset_print_rrsig(FILE* fd, rrset_type* rrset);
+char* rrset_get_label(rrset_type* rrset);
+
+double get_jitter_step(char* str);
#endif /* SIGNER_RRSET_H */
Index: signer/src/signer/zonedata.c
===================================================================
--- signer/src/signer/zonedata.c (revision 3778)
+++ signer/src/signer/zonedata.c (working copy)
@@ -772,7 +772,7 @@
return 1;
}
- now = time_now();
+ now = time_cur_hour();
ctx = hsm_create_context();
if (!ctx) {
se_log_error("error creating libhsm context");
Index: signer/src/util/duration.c
===================================================================
--- signer/src/util/duration.c (revision 3778)
+++ signer/src/util/duration.c (working copy)
@@ -419,7 +419,27 @@
return time(NULL);
}
+/**
+ * Return the time since Epoch in seconds, rounded to the hour
+ *
+ */
+time_t
+time_cur_hour(void)
+{
+ time_t tmp_t = 0;
+#ifdef ENFORCER_TIMESHIFT
+ const char* env = getenv("ENFORCER_TIMESHIFT");
+ if (env) {
+ tmp_t timeshift2time(env);
+ } else
+#endif /* ENFORCER_TIMESHIFT */
+ tmp_t = time(NULL);
+
+ return HOUR_T*(tmp_t/HOUR_T);
+}
+
+
/**
* copycode: This code is based on the EXAMPLE in the strftime manual.
*
Index: signer/src/util/duration.h
===================================================================
--- signer/src/util/duration.h (revision 3778)
+++ signer/src/util/duration.h (working copy)
@@ -39,6 +39,9 @@
#include <stdint.h>
#include <time.h>
+/* Number of seconds in an hour, used by time_cur_hour to round down */
+#define HOUR_T 3600
+
/**
* Duration.
*
@@ -144,6 +147,7 @@
*
*/
time_t time_now(void);
+time_t time_cur_hour(void);
/**
* Clean up duration.
<<inline: signature-expiration.png>>
_______________________________________________ Opendnssec-user mailing list [email protected] https://lists.opendnssec.org/mailman/listinfo/opendnssec-user
