Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Eosjs-ecc produced different signature comparing to eos with same parameters #121

Closed
ceeji opened this issue May 27, 2018 · 7 comments
Closed

Comments

@ceeji
Copy link

ceeji commented May 27, 2018

I found eosjs-ecc will produce different signature with same data and same private key.

For example, when I generate signatures for byte[32] which is filled with zero from EOS like this (the private key below is just for test so it is safe to post it):

char b[32];
    memset(b, 0, sizeof(b));
    auto sb = sha256(b, sizeof(b));
    auto strpkey = std::string("5HxQKWDznancXZXm7Gr2guadK7BhK9Zs8ejDhfA9oEBM89ZaAru");
    auto pkey = eos::chain::private_key_type(strpkey);
    auto sig2 = pkey.sign(sb);
    auto strsig2 = (std::string)sig2;
    printf("%s\n", strsig2.c_str());

And the output is different from generating signatures with same parameters from eosio-ecc:

const ecc = require('./eosjs-ecc');

var pkey = '5HxQKWDznancXZXm7Gr2guadK7BhK9Zs8ejDhfA9oEBM89ZaAru';
var buf = Buffer.alloc(32, 0);
var sig = ecc.signHash(buf, pkey);
console.log(sig);

So I can not use the signature to call APIs of EOS. What is the problem?

PS: I have confirmed the signature signed by eosjs-ecc can be virefied succesful by verifyHash as follow:

const ecc = require('./eosjs-ecc');

var pkey = '5HxQKWDznancXZXm7Gr2guadK7BhK9Zs8ejDhfA9oEBM89ZaAru';
var buf = Buffer.alloc(32, 0);
var sig = ecc.signHash(buf, pkey);
console.log(sig);

var pubkey = ecc.privateToPublic(pkey);
console.log(pubkey);
var r = ecc.verifyHash(sig, buf, pubkey);
console.log(r);

console.log(ecc.recoverHash(sig, buf));
@ceeji ceeji changed the title Eosjs-ecc Eosjs-ecc produced different signature comparing to eos did with same parameters May 27, 2018
@ceeji
Copy link
Author

ceeji commented May 27, 2018

Since I am signing only a 32-bit zero array, so this problem is surely not relative to ABI, structs or something else.

@jcalfee
Copy link
Contributor

jcalfee commented May 27, 2018

Do you know of a easy way to run c++ code like you provided outside of the eos source tree? Every-time I hack something in eos source tree I end up deleting it or loosing it in my git stashes .. lol

@ceeji
Copy link
Author

ceeji commented May 27, 2018

@jcalfee Why you want to run it out of the source tree? You can easily restore your code via git so you can just paste the code to eos's source code.

Anyone who know the reason of the topic? Thanks.

@jcalfee
Copy link
Contributor

jcalfee commented May 27, 2018

Have a look over here:
possibly related: EOSIO/eosjs-ecc#17

@ceeji ceeji changed the title Eosjs-ecc produced different signature comparing to eos did with same parameters Eosjs-ecc produced different signature comparing to eos with same parameters May 27, 2018
@ceeji
Copy link
Author

ceeji commented May 27, 2018

@jcalfee Thanks. I know EOS use special technology to make the signature "canonical ", but eosjs-ecc itself is aimed to meet the requirement of EOS. And from its source code I can see it has alread done the things needed to produce a valid signature.

I have read the code in eosjs-ecc to sign a hash:

while (true) {
        ecsignature = ecdsa.sign(curve, dataSha256, privateKey.d, nonce++);
        der = ecsignature.toDER();
        console.log("der: " + der.toString('hex'))
        lenR = der[3];
        lenS = der[5 + lenR];
        if (lenR === 32 && lenS === 32) {
            i = ecdsa.calcPubKeyRecoveryParam(curve, e, ecsignature, privateKey.toPublic().Q);
            i += 4; // compressed
            i += 27; // compact  //  24 or 27 :( forcing odd-y 2nd key candidate)
            break;
        }
        if (nonce % 10 === 0) {
            console.log("WARN: " + nonce + " attempts to find canonical signature");
        }
    }

It seems to be fantastic.

But the signature it returns is not the same as EOS chain does. So why is it? It is really strange.

@ceeji
Copy link
Author

ceeji commented May 27, 2018

For example, when i signed 32-bit zeros, EOS produces SIG_K1_Jz9d1rKmMV51EY6dnU3pNaDiLvGTeVdxDZGvJEfAkdcwzs97gNg5yYPhPSdEg33Jyp5736Tnnzccf1p6h6vedXpHSUBio1 and eosjs-ecc produces SIG_K1_KjLTq9WozaHp2fNNfSZmTzcqiu82gPcVU3ZyaEZJgH3WykSANvun9t3Pw6Z2xvbAcz24rcKBADWG7nvzq9wAobpq62CYVC.

Anyone who has ideas about this?

@jcalfee
Copy link
Contributor

jcalfee commented Jun 13, 2018

Moving this ticket to here => EOSIO/eosjs-ecc#20

Transaction uniqueness is checked on the unsigned transaction, not the signed transaction. Additionally @arhag points out there are extra checks for superfluous signatures protecting bandwidth. So I will not re-add the high-priority label. That said, we do intend to closely followed RFC 6979 signature algorithm.

@jcalfee jcalfee closed this as completed Jun 13, 2018
metamaster2021 pushed a commit to armoniax/eosjs that referenced this issue May 7, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants