Signature
ECDSA 簽名算法中的 nonce 使用
我正在嘗試理解簽名函式 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 的原因是因為您需要創建兩個未知數,以便人們無法從公鑰逆向工程私鑰。
每次您簽署交易時,此隨機數都必須是隨機的。如果你使用相同的隨機數,那麼攻擊者將有兩個方程和只有兩個可以逆向工程的未知數。