Post
Topic
Board Development & Technical Discussion
Merits 1 from 1 user
Re: ECDSA math questions
by
arulbero
on 27/12/2018, 16:26:31 UTC
⭐ Merited by Piggy (1)
Let (r,s) be the signature, m the message, e = H(m) the message digest, G the curve generator, d the private key, P=d*G the public key.

ECDSA works this way:
1) pick a random nonce k (a private key you use once) in [1,n-1]
2) k -> k*G = Q(xq,yq)   then r = xq mod n (r is more or less like the x coordinate of Q)
3) s = k^-1 * (r*d + e)  mod n

Then k*s = (r*d + e) mod n --> e = (s*k - r*d)  mod n     you know r and s (the signature) but not k and s (the two private keys), then you cannot retrieve the value of 'e'. (Usually you know 'e' too, in that case if you found out k, you could get d easily or viceversa, because it would be an equation with 4 known values and only 1 unknown.)

You could retrieve only e*G, because:

e*G = s*k*G - r*d*G = s*Q - r*P  mod n,  but again from e*G you can't retrieve the message digest 'e' (it would be like getting a private key from the public one).

Usually, when you verify a signature, you know 'e', and s*Q = e*G + r*P mod n -> Q = s^-1*e*G + s^-1*r*P, the last equation can be verified by knowing r, s, e, P.

Let's give an example.

From here: http://www.righto.com/2014/02/bitcoins-hard-way-using-raw-bitcoin.html

we see how this tx was constructed

we get this data:

Code:
>>> n=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 (this is the group order)
>>>
>>> d=0x0caecf01d74102a28aed6a64dcf1cf7b0e41c4dd6c62f70f46febdc32514f0bd (the private key)
>>> e=0x5fda68729a6312e17e641e9a49fac2a4a6a680126610af573caab270d232f850 (the double hash of the tx/message)
>>>
>>> r=0x2cb265bf10707bf49346c3515dd3d16fc454618c58ec0a0ff448a676c54ff713 (the first part of the signature)
>>> s=0x6c6624d762a1fcef4618284ead8f08678ac05b13c84235f1654e6ad168233e82 (the second part of the signature)


Now we try to retrieve the random nonce k  (remember,  k -> k*G = Q(xq,yq)  then r = xq mod n , namely r is the x coordinate of Q, a sort of a public key, and k is its private key)

e = (s*k - r*d)  mod n

s*k = (e + r*d) mod n

k = s^-1 * (e + r*d) mod n

Code:
>>> s_inv=pow(s,n-2,n)  --> we are using the Fermat's little theorem to compute 1/s
>>> hex(s_inv)
'0x947f7b9fc41f37348c3a53a146757b9759e79da5fe039a35a9024bec1fb0ea0cL'
>>>
>>> hex((s_inv * s) % n)  --> we check that s_inv * s = 1
'0x1L'
>>>
>>> k=(s_inv * (e + r*d)) % n
>>> hex(k)
'0x4526b5ab1973ab68afd06517996d22823441dd9ef52663a57de11d6642e961e7L'

k is supposed to be the private key to r.

To have a confirm let's put  4526b5ab1973ab68afd06517996d22823441dd9ef52663a57de11d6642e961e7  here and

we get the public key

Code:
04
X = 2CB265BF10707BF49346C3515DD3D16FC454618C58EC0A0FF448A676C54FF713
Y = B317A494AB75813F8737AC779BDF68AC5235C683A0FF92AEB81655DE137FB862

As expected, X = r !