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的方式工作
-
在signature.js中的
signHash
方法中,將初始隨機數更改爲1:
-
在ecdsa.js的
deterministicGenerateK
方法中,稍微更改循環結構:
它現在與eos產生完全相同的簽名
-
結論: 簽名不是唯一的, 但始終能恢復出相同的公鑰。給定哈希和私鑰在此鏈上的簽名不需要匹配,它們只需要規範且有效。
https://github.com/EOSIO/eosjs-ecc/issues/20