Page MenuHomePhabricator

[Cashtab] Use ecash-lib to sign and verify msgs
Needs ReviewPublic

Authored by bytesofman on Tue, Mar 11, 17:39.

Details

Reviewers
None
Group Reviewers
Restricted Project
Summary

Now that we have the methods in our own stack to do this, implement in Cashtab. This allows us to stop using bitcoinjs-message.

Test Plan

npm test

Diff Detail

Repository
rABC Bitcoin ABC
Branch
ecash-lib-sign-msgs
Lint
Lint Errors
SeverityLocationCodeMessage
Errorcashtab/src/components/SignVerifyMsg/SignVerifyMsg.js:20ESLINT@typescript-eslint/no-unused-vars
Unit
No Test Coverage
Build Status
Buildable 32670
Build 64828: Build Diffecash-wallet-tests · ecash-lib-integration-tests · ecash-agora-integration-tests · ecash-agora-tests · ecash-lib-tests · cashtab-tests
Build 64827: arc lint + arc unit

Event Timeline

implement a de facto spec implementation of sign and verify at the lib level and apply in Cashtab

drop now-unused component function

use real "custom" prefix, back out forbid only change (should be its own diff)

bytesofman added inline comments.
cashtab/src/components/SignVerifyMsg/__tests__/SignVerifyMsg.test.js
81 ↗(On Diff #53033)

the signature changing is ... potentially not expected behavior. I am not sure why it changes. The prefixes are identical. There are some conventions in bitcoinjs-message that could lead to distinct values, i.e. adjusting the recovery byte

https://github.com/bitcoinjs/bitcoinjs-message/blob/master/index.js#L34

does electrum / the node do this?

81 ↗(On Diff #53032)

the signature changing is ... potentially not expected behavior. I am not sure why it changes. The prefixes are identical. There are some conventions in bitcoinjs-message that could lead to distinct values, i.e. adjusting the recovery byte

https://github.com/bitcoinjs/bitcoinjs-message/blob/master/index.js#L34

does electrum / the node do this?

cashtab/src/components/SignVerifyMsg/__tests__/SignVerifyMsg.test.js
81 ↗(On Diff #53033)

does electrum do this

relevant file looks like electrumabc/ecc.py

def sign_message(
        self,
        message: bytes,
        is_compressed,
        *,
        sigtype: SignatureType = SignatureType.ECASH,
    ) -> bytes:

        def bruteforce_recid(sig_string):
            for recid in range(4):
                sig65 = construct_sig65(sig_string, recid, is_compressed)
                if not self.verify_message(sig65, message, sigtype=sigtype):
                    continue
                return sig65, recid
            else:
                raise Exception("error: cannot sign message. no recid fits..")

        message = to_bytes(message, "utf8")
        msg_hash = Hash(msg_magic(message, sigtype))
        sig_string = self.sign(
            msg_hash,
            sigencode=sig_string_from_r_and_s,
        )
        sig65, recid = bruteforce_recid(sig_string)
        return sig65

ref

def construct_sig65(sig_string, recid, is_compressed):
    comp = 4 if is_compressed else 0
    return bytes([27 + recid + comp]) + sig_string

so, it looks like there is a standard as such about signing with / without a compressed key ... and the standard exists bc we need to know which key to recover.

that said ... I'm not sure we need to have this in ecash-lib.

the way ecash-lib is contained, we would always be signing with 32-byte sk, and always be verifying against the 33-byte compressed public key.

So question -- do we need to support uncompressed public keys? Cashtab does not need this.

I can see the value in having deterministic signatures for any given private key tho.