Skip to content

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

@erickcestari

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions