-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Encode unpadded length of payload #375
Conversation
e1b17fe
to
ed0555c
Compare
In another chat, you presented the problem this solves to me as follows:
and
Do we know of any PSBT parsing implementations that suffer this behavior that does not follow the specification? i.e. rejecting instead of ignoring trailing nulls I'm going to suggest simpler ways to solve this. Potentially stupid:
Help me understand whether or not adding the complexity of BOLT 1 TLV encoding is a strict necessity or if it's just a nice-to-have to prevent a theoretical problem |
BIP 174 (and 370) doesn't say anything about ignoring trailing null bytes, only to ignore (but preserve) unknown fields. Strictly speaking NULL bytes are interpretable, since 4 null bytes are a valid key value pair in BIP 174 consisting of type 0 and empty key and value, then if there's 4n trailing bytes this adds n keypairs, with duplicate (empty) keys, so that's in violation of the spec. If there's a number of trailing bytes that isn't a multiple of 4, then i'm not sure what happens.
I don't think this is simpler compared to encoding the length, there are edge cases. For example, if the last keypair in the output map has a value that ends in a null byte, there would need to be two null bytes at the end of the PSBT or it'll be truncated.
That's the point of making this a valid TLV, the type can be something other than 0,
The specification I'm suggesting in BIP 77 is: The first byte must be 0, followed by a BOLT-1 BigSize encoded length, followed by that many bytes. Trailing bytes must be ignored So not actually a TLV stream as far as BIP 77 is concerned, just forwards compatible with TLV stream. The simpler approach is to specify that it's always prefixed with a signed 16 bit value which must be positive (if it's negative then that's an incompatible version, i.e. top bit is reserved as a type bit effectively). I prefer the TLV approach, either BOLT-1 or the |
The answer appears to be no, and it's just a strict interpretation of the BIP174 spec that's caught your attention. I'm inclined to close this wontfix since it seems like client PSBT parsers could address this on their own. Have you been bitten by a problem like this before or was it just a careful reading of the spec that brought it up? |
@nothingmuch help me understand
Can you add more color to what this modification would look like? Are you talking about serializing the pubkey in certain message types by default so that we wouldn't need to implement that in We've already got a bitcoin-hpke update in this next release, so the time for breaking changes and updating deps is now |
No, simpler: In both encrypt_message_{a,b}, first allocate a The only motivation is that it makes the bounds checking a little easier to reason about IMO. From a performance standpoint this is a silly micro-optimization, so not a justification by any means. FWIW, if you're cACK on length tagging and I should improve this PR, I also just learned that For the public record, I made two mistakes in this PR that Dan pointed out in chat:
Therefore the only remaining justifications are:
|
Although BIP 174 PSBTs are self terminating, storing the length in the encrypted payload avoid any behavioral dependency on a PSBT parser ignoring any trailing data (the NULL byte padding). This is encoded as a BOLT 1 TLV[^1] record with type 0 (and therefore also a valid TLV stream), facilitating forward compatibility with BIP 77 extensions that might not necessarily signal receiver capabilities in the BIP 21 URI. This implementation si,mply ignores any trailing data which would contain any subsequent TLV records with a type larger than 0. Since payloads are at most 7168 bytes (including the overhead), the unpadded plaintext length will always fit in 16 bits. For very small payloads this value is possibly less than 253 (0xfd), resulting in an 8 bit length. [^1]: https://github.com/lightning/bolts/blob/master/01-messaging.md#type-length-value-format
35c7d50
to
c3d58ac
Compare
rebased to unbreak the newly merged test |
This change enforces that messages have a uniform length at the type level. If bitcoin-hpke was modified to retain the underlying in-place interface then this code could be further simplified so that there is only one PADDED_MESSAGE_BYTES length buffer shared by all steps, which would also save a copy step.
- constants instead of magic numbers - `&mut [u8]` implements Write, no need for Cursor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My only issue is the unused PADDED_MESSAGE_BYTES
import
#[cfg(feature = "v2")] | ||
use crate::hpke::PADDED_MESSAGE_BYTES; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This appears not to be used anywhere
Closing this since we agreed that this change is not necessary, will followup with BIP 77 PRs to clarify why it isn't necessary after finishing some other stuff. Are the changes from |
Although BIP 174 PSBTs are self terminating[edit: actually they aren't, see belownvm keylen=0 is syntactically invalid, not just semantically c.f. https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#cite_note-1], storing the length in the encrypted payload avoid any behavioral dependency on a PSBT parser ignoring any trailing data (the NULL byte padding).This is encoded as a BOLT 1 TLV1 record with type 0 (and therefore also a valid TLV stream), facilitating forward compatibility with BIP 77 extensions that might not necessarily signal receiver capabilities in the BIP 21 URI. This implementation si,mply ignores any trailing data which would contain any subsequent TLV records with a type larger than 0.
Since payloads are at most 7168 bytes (including the overhead), the unpadded plaintext length will always fit in 16 bits. For very small payloads this value is possibly less than 253 (0xfd), resulting in an 8 bit length.
Footnotes
https://github.com/lightning/bolts/blob/master/01-messaging.md#type-length-value-format ↩