Signature

ECDSA 簽名算法中的 nonce 使用

  • February 1, 2019

我正在嘗試理解簽名函式 secp256k1_ecdsa_sig_sign(),我很好奇這裡的 nonce 用法。

static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) {
 unsigned char b[32];
 secp256k1_gej rp;
 secp256k1_ge r;
 secp256k1_scalar n;
 int overflow = 0;

 secp256k1_ecmult_gen(ctx, &rp, nonce);
 secp256k1_ge_set_gej(&r, &rp);
 secp256k1_fe_normalize(&r.x);
 secp256k1_fe_normalize(&r.y);
 secp256k1_fe_get_b32(b, &r.x);
 secp256k1_scalar_set_b32(sigr, b, &overflow);
 /* These two conditions should be checked before calling */
 VERIFY_CHECK(!secp256k1_scalar_is_zero(sigr));
 VERIFY_CHECK(overflow == 0);

 if (recid) {
   /* The overflow condition is cryptographically unreachable as hitting   it requires finding the discrete log
    * of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria.
    */
    *recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
 }
 secp256k1_scalar_mul(&n, sigr, seckey);
 secp256k1_scalar_add(&n, &n, message);
 secp256k1_scalar_inverse(sigs, nonce);
 secp256k1_scalar_mul(sigs, sigs, &n);
 secp256k1_scalar_clear(&n);
 secp256k1_gej_clear(&rp);
 secp256k1_ge_clear(&r);

 if (secp256k1_scalar_is_zero(sigs)) {
   return 0;
 }

 if (secp256k1_scalar_is_high(sigs)) {
   secp256k1_scalar_negate(sigs, sigs);

   if (recid) {
     *recid ^= 1;
   }

 }

 return 1;
}

我對標準 ECDSA 很熟悉,但是這裡的 nonce 究竟是做什麼的,為什麼?

謝謝!

Pieter Wuille 在評論中回答:

那隻是ECDSA。nonce 是簽名的隨機性,與被簽名的消息無關。ECDSA 簽名是一對 (r,s),其中 r 是 kG 的 X 座標,並且 s = (m+r*x)/k(其中 k=nonce,m=消息雜湊,x=私鑰,G=曲線發生器)。

secp256k1 函式中使用的 nonce 是一個隨機私鑰,它是為了生成最終簽名而生成的。要對消息“ m ”簽名,請使用您的私鑰鎖定該消息並生成唯一簽名。簽名有兩個分量(R,S)。

第一步是使用隨機數(比如k)計算 R。這個隨機數是在 nonce 的幫助下生成的。下一步是使用與比特幣相同的生成點使用此隨機數計算公鑰。這意味著P = k*G。那麼 P 的 x 座標就是 R。

假設您用於簽署簽名的原始私鑰是dA。那麼簽名的 S 分量為:

S = (k^(-1))(hash(m) + dA*R) ----- where k is your nonce

比特幣交易中的簽名欄位既有R又有S。你取這個分量,計算方程的值

S^(-1)*hash(m)*G + S^(-1)*R*Qa ----- where Qa is the public key of your private key qA

如果該方程的 x 座標等於 R,則簽名有效。因此,在不洩露私鑰的情況下,您可以通過私鑰的數字簽名來驗證交易的真實性。使用 nonce 的原因是因為您需要創建兩個未知數,以便人們無法從公鑰逆向工程私鑰。

每次您簽署交易時,此隨機數都必須是隨機的。如果你使用相同的隨機數,那麼攻擊者將有兩個方程和只​​有兩個可以逆向工程的未知數。

引用自:https://bitcoin.stackexchange.com/questions/84055