密碼學系列 - 爲什麼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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章