Skip to content

Incorrect signature verification edge cases #3314

Description

@morehouse

BOLT 7 states in multiple places that gossip message signatures are to be verified over the actual message bytes. For example, for channel_update:

The receiving node:

  • if signature is not a valid signature, using node_id of the double-SHA256 of the entire message following the signature field (including unknown fields following fee_proportional_millionths):
    • SHOULD send a warning and close the connection.
    • MUST NOT process the message further.

But Eclair actually re-encodes messages through its own codec before verifying signatures, and for certain fields the round trip can change the underlying bytes:

  • characters after the first null byte are stripped from alias
  • features bitvectors are changed to minimal form
  • message_flags and channel_flags have the upper bits stripped

When this occurs, Eclair verifies signatures incorrectly and may reject gossip that other implementations accept, or vice versa.

Implications

While a spec-conforming node should never create gossip that triggers these bugs, a buggy or malicious node could do it and cause Eclair's view of the LN network to diverge from other nodes' views.

A more concerning network isolation vector could arise if any implementation ever decides to ban peers that repeatedly send gossip with incorrect signatures. While no implementation does this currently, Eclair does have a TODO indicating the intention to do it in the future:

case GossipDecision.InvalidSignature(r) =>
val bin: String = LightningMessageCodecs.meteredLightningMessageCodec.encode(r) match {
case Attempt.Successful(b) => b.toHex
case _ => "unknown"
}
log.error(s"peer sent us a routing message with invalid sig: r=$r bin=$bin")
// for now we just send a warning, maybe ban the peer in the future?
// TODO: this doesn't actually disconnect the peer, once we introduce peer banning we should actively disconnect
d.transport ! Warning(s"invalid announcement sig (bin=$bin)")
d.behavior

Reproducing

0001-Demonstrate-signature-verification-bugs.patch

Discovery

This issue was surfaced while fuzzing node_announcements using Smite. Eclair failed to verify the signature when alias had trailing non-null bytes after the initial null byte, while other implementations succeeded in verifying the signature.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions