密码学系列 - 为什么EOSIO的签名与EOSJS的签名结果不一样

EOSIO

In eos the initial value of nonce is 1

static int extended_nonce_function( unsigned char *nonce32, const unsigned char *msg32,
                                        const unsigned char *key32, unsigned int attempt,
                                        const void *data ) {
    unsigned int* extra = (unsigned int*) data;
    (*extra)++; //这是初始计数器值,从0变到1
    return secp256k1_nonce_function_default( nonce32, msg32, key32, *extra, nullptr );
}

static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) {
   secp256k1_rfc6979_hmac_sha256_t rng;
   unsigned int i;
   secp256k1_rfc6979_hmac_sha256_initialize(&rng, key32, 32, msg32, 32, (const unsigned char*)data, data != NULL ? 32 : 0);
   for (i = 0; i <= counter; i++) { //因为此计数器在第一次被设置为1,所以循环将执行两次,并且第一个K被忽略!!!!
       secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
   }
   secp256k1_rfc6979_hmac_sha256_finalize(&rng);
   return 1;
}

EOSJS

  • eosjs-ecc算法也是OK的,它提供了一个有效的签名 (一个哈希可以有很多有效的签名,而不仅仅是一个)。唯一的区别是eos从第二个k开始搜索,而eosjs-ecc从第一个k开始搜索,因此有时它们会产生不同的结果(但这些结果都是合法结果)

  • 可以调整eosjs-ecc循环代码以忽略第一个k,使其严格按eos的方式工作

    1. 在signature.js中的signHash方法中,将初始随机数更改为1:

    2. 在ecdsa.js的deterministicGenerateK方法中,稍微更改循环结构:

      它现在与eos产生完全相同的签名

结论: 签名不是唯一的, 但始终能恢复出相同的公钥。给定哈希和私钥在此链上的签名不需要匹配,它们只需要规范且有效。

https://github.com/EOSIO/eosjs-ecc/issues/20

发布了70 篇原创文章 · 获赞 81 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/wcc19840827/article/details/105203049
今日推荐