-
|
When signing and validating SIG(0), I need to calculate the signature data of the DNS request/response without any SIG RRsets. After stripping the SIG RRsets I call
|
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 4 replies
-
|
would become The way to ensure that there is NO reordering of RRs is to pass |
Beta Was this translation helpful? Give feedback.
-
|
While it might be useful to have a way to disable shuffling, I don't think this is sufficient for SIG(0), at least for verifying. It's been a while since I've looked at SIG(0), but I think you need the exact message bytes. Rendering a parsed message isn't guaranteed to create identical output, because of name compression. |
Beta Was this translation helpful? Give feedback.
-
|
I have some code that might help, let me check it out and get back to you before you write anything. |
Beta Was this translation helpful? Give feedback.
-
|
I think there are two basic ways to go about this. One is to basically do things the way TSIG is handled, which is inside of message from_wire() and to_wire(). The other way is to have some separate signing code that works on wire format. For the TSIG-like way: Adding a SIG(0) RR to the end of the additional section in to_wire() would not change anything that was previously converted to wire other than the RR count for the additional data section. The TSIG code in Message.to_wire() is already doing things this way. For verification, if you do it in the _WireReader like TSIG does, you have access to the original wire data and the code is already walking through the message for you. Though I guess you have to copy at least the header so you can change the additional count as the original wire data is immutable. The TSIG-like way is probably the most consistent way to handle it in "dnspython style", though presumably needs a "SIG(0) keyring" parameter. A more standalone approach would just be given a blob of wire format and either check or add the SIG(0) to it. In this case, you'd use the dns.wire.Parser to navigate the message and find where the SIG(0) started. The "code that might help" I mentioned above is a thin veneer on top of the parser to find where the beginning and end offsets of all the RRs are in the message. That way once you know the starting offset of the SIG(0) you can just slice everything before it. I prefer the TSIG-like approach at the moment, as it means you'd only have to parse the message once in normal from_wire() usage instead of having to deal with SIG(0) in a separate pass. Given my current caffeine level, it is possible I am missing things, so I'd be glad to hear what Brian thinks :) |
Beta Was this translation helpful? Give feedback.
-
|
For signing, I agree that SIG(0) should be similar to TSIG. I don't know if the logic is identical, but it's close enough that it should probably be done in the same way. For verification, it's potentially more difficult, for multiple reasons. I believe there can be multiple SIG(0) records, which means keeping track of multiple offsets. And unlike TSIG, which is symmetric, the caller doesn't necessarily know what keys will have generated signatures before parsing the message. I'd expect similar logic as TSIG to work, but might be missing something. It might be possible to use the same keyring parameter, as it's called "keyring", if there's some way to add extra forms of it that would make sense for SIG(0). That would have the advantage of not changing nearly as many function signatures, if it made sense. |
Beta Was this translation helpful? Give feedback.
message.to_wire(want_shuffle=False)will turn off shuffling, but that may not be enough because dnspython will still be assembling RRsets from the wire. If some pathological code emitted RRs in an RRset interleaved with RRs from another RRset, the order would still change, e.g.would become
The way to ensure that there is NO reordering of RRs is to pass
one_rr_per_rrset=Truewhen parsing the message. This puts every RR into an RRset of one rdata.