### 区块链中的数学 - sm2恢复公钥问题

• blocksight
• 更新于 2020-10-17 12:33
• 阅读 3900

## sm2签名恢复过程

\$s = (1+d_A)^{-1}（k - r d_A ）\ mod\ n\$

\$s (1+d_A) G = sG + sd_AG = sG + sP_A = kG - r d_AG = kG - rP_A\$

k是未知的，令曲线上的点R = kG ， 签名结果中的r就是点R的x坐标（参见签名过程步骤3，4，5可知），于是：

\$P_A= (s+r)^{-1}* (R - sG)\$

## 具体实现

``````func recoverKeyFromSignatureSM2(curve P256V1Curve,ee *big.Int, sig *Sm2Signature, msg []byte,
iter int, doChecks bool) (*PublicKey, error) {
// 1.1 x = (n * i) + r - e
Rx := new(big.Int).Mul(curve.Params().N,
new(big.Int).SetInt64(int64(iter/2)))
Rx.Sub(Rx,ee)

if Rx.Cmp(curve.Params().P) != -1 {
return nil, errors.New("calculated Rx is larger than curve P")
}

// convert 02&lt;Rx> to point R. (step 1.2 and 1.3). If we are on an odd
// iteration then 1.6 will be done with -R, so we calculate the other
// term when uncompressing the point.
Ry, err := decompressPointSM2(curve, Rx, iter%2 == 1)
if err != nil {
return nil, err
}
// 1.4 Check n*R is point at infinity
if doChecks {
nRx, nRy := curve.ScalarMult(Rx, Ry, curve.Params().N.Bytes())
if nRx.Sign() != 0 || nRy.Sign() != 0 {
return nil, errors.New("n*R does not equal the point at infinity")
}
}

// 1.5 calculate e from message using the same algorithm as ecdsa
// signature calculation.
// e := hashToInt(msg, curve)

// Step 1.6.1:
// We calculate the two terms sR and eG separately multiplied by the
// inverse of r (from the signature). We then add them to calculate
// Q = (s+r)^-1(R-sG)
// first term.
// invrS := new(big.Int).Mul(invr, sig.S)
// invrS.Mod(invrS, curve.Params().N)
sRx, sRy := curve.ScalarMult(Rx, Ry, invr.Bytes())
s := new(big.Int).Set(sig.S)
// second term.
s.Neg(s)
s.Mod(s, curve.Params().N)
s.Mul(s, invr)
s.Mod(s, curve.Params().N)
minuseGx, minuseGy := curve.ScalarBaseMult(s.Bytes())

// TODO: this would be faster if we did a mult and add in one
// step to prevent the jacobian conversion back and forth.
Qx, Qy := curve.Add(sRx, sRy, minuseGx, minuseGy)
return &PublicKey{
Curve: curve,
X:     Qx,
Y:     Qy,
}, nil
}``````

Java语言实现好像还没有现成的，抽时间可以写一个，如果你知道的话，也可以分享下！

blocksight