Skip to content

Bolt11: Signature verification fails after public key recovery due to s-value malleability #802

Description

@erickcestari

Found through differential fuzzing: When decoding a bolt11 invoice the current code performs redundant signature verification after public key recovery, which fails due to ECDSA s-value malleability:

val msg = Crypto.sha256(tohash)
val nodeId = Crypto.recoverPublicKey(sig, msg, recid.toInt())
val check = Crypto.verifySignature(msg, sig, nodeId)  // This fails unnecessarily
require(check) { "invalid signature" }

Root Cause:

  • recoverPublicKey accepts both high-s and low-s signatures
  • verifySignature only accepts low-s signatures (normalized)
  • This creates a mismatch when the signature has a high s-value

Proposed Solution:
Remove the redundant verification check since recoverPublicKey already guarantees signature validity. The additional verifySignature call provides no security benefit but introduces compatibility issues.

Invoice deserialization failed for lnbc1qqygh9qpp5s7zxqqyqqqqqqqqyqqqqcqqqqqqqqqqqqcqpjqqqqqqqqqqqqqqqdqqqqqqqqqqqqqqqqqqqqqqqcqpjqqqqqqqq2qqqqqqqqqqqqqqqqqcqpjqqqqqqqqqqqqqqqqqqqqqqqqsqqqqqdqqqqqqqqqqqqqqrqqqt42398
Module: Lnd
Result: No error
Module: LightningKmp
Result: invalid signature

This is a known issue documented in secp256k1: bitcoin-core/secp256k1#1718

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    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