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)
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
Must FAIL on main today and PASS after the fix.
Reference
Report 2 (private)