Skip to content

cose: route signMessage through COSE domain separation #389

@solidsnakedev

Description

@solidsnakedev

Summary

SigningWallet.signMessage signs the caller payload directly with PrivateKey.sign, using the same key and primitive as signTx and with no CIP-8/COSE wrapping. If the payload is a 32 byte transaction body hash, the result is a valid VKeyWitness for that transaction, so signMessage can act as a transaction signing oracle. The repo already ships a correct COSE_Sign1 implementation in cose/SignData.ts that this path bypasses.

Affected

packages/evolution/src/sdk/client/internal/Signing.ts signMessage (L362-372)
correct impl available: packages/evolution/src/cose/SignData.ts

Fix

Route signMessage through the existing cose/SignData COSE_Sign1 implementation so the signed bytes are domain separated (Sig_structure with the "Signature1" context and the address in the protected headers). Return a CIP-30 DataSignature { signature, key } rather than a bare hex signature.

Regression test

  • given: a wallet derived from a mnemonic, and h = a 32 byte transaction body hash
  • before fix: signMessage(address, h) returns a signature where VKey.verify(paymentVKey, h, sig) === true (a valid tx witness)
  • after fix: the signed bytes are a COSE Sig_structure, so VKey.verify(paymentVKey, h, ...) over the raw hash === false, and the output parses as a valid COSE_Sign1

Must FAIL on main today and PASS after the fix.

Reference

Report 2 (private)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    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