Title: Compressed keys, Y from X Post by: jackjack on April 01, 2013, 12:56:54 AM Hi,
I'd like to know if there is a formula to calculate the two possible values of Y from X I use a library that needs them, and I don't really want to modify it Title: Re: Compressed keys, Y from X Post by: Zeilap on April 01, 2013, 01:12:55 AM Hi, Actually it's very simple. I'd like to know if there is a formula to calculate the two possible values of Y from X I use a library that needs them, and I don't really want to modify it y2 = x3+ ax2 + b so we need to perform square root to recover y from x. And it turns out that sqrt(a) = a(q+1)/4 Now you just have to pick either the positive or negative solution. If the y that you calculated is even, and the first byte of the key is even, then use this value, otherwise, use the negative value which is q-y. EDIT: relevant code I wrote as a patch for bitaddress.org Code:
Title: Re: Compressed keys, Y from X Post by: jackjack on April 01, 2013, 02:06:38 AM Thanks, that helps a lot!
I still have a problem though, the equation doesn't match my data (I wanted to check on an example first) Let's take that example: Quote secret: 0123456789012345678901234567890123456789012345678901234567890123 public key: 046655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515217e88dd05e93 8efdd71b2cce322bf01da96cd42087b236e8f5043157a9c068e -> X: 6655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515 Y: 217e88dd05e938efdd71b2cce322bf01da96cd42087b236e8f5043157a9c068e I get: y2=7f65351d4485d7656f60f8a4e5c802cc5ba6a1eae5d0e94b63357ab43d18b53e x3=368e518c43bee254854b3c43aa9893e65a3d19282468bae274e93e5cb93d0946 Whereas I should have y2 = x3 + 7 (secp256k1) Title: Re: Compressed keys, Y from X Post by: Zeilap on April 01, 2013, 02:52:53 AM Thanks, that helps a lot! I don't get these values for x3 and y2. I getI still have a problem though, the equation doesn't match my data (I wanted to check on an example first) Let's take that example: Quote secret: 0123456789012345678901234567890123456789012345678901234567890123 public key: 046655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515217e88dd05e93 8efdd71b2cce322bf01da96cd42087b236e8f5043157a9c068e -> X: 6655feed4d214c261e0a6b554395596f1f1476a77d999560e5a8df9b8a1a3515 Y: 217e88dd05e938efdd71b2cce322bf01da96cd42087b236e8f5043157a9c068e I get: y2=7f65351d4485d7656f60f8a4e5c802cc5ba6a1eae5d0e94b63357ab43d18b53e x3=368e518c43bee254854b3c43aa9893e65a3d19282468bae274e93e5cb93d0946 Whereas I should have y2 = x3 + 7 (secp256k1) x3 = ec4081ea3487eadbad1ec86b4fca367185932b0a435c30a4b570b5535e37b17c y2 = ec4081ea3487eadbad1ec86b4fca367185932b0a435c30a4b570b5535e37b183 If you load up bitaddress.org and then use 'Web console' in Firefox or 'Javascript console' in Chrome you can try it out like this Code: > var curve = EllipticCurve.getSECCurveByName('secp256k1').getCurve() Title: Re: Compressed keys, Y from X Post by: jackjack on April 01, 2013, 12:41:17 PM Wow I can't even use correctly my library...
I'll look at that to get it sorted and hopefully report the success soon Title: Re: Compressed keys, Y from X Post by: jackjack on April 01, 2013, 01:48:31 PM Yep, that works, thanks a lot!
EDIT: I still have a question: how do you know that sqrt(a) = a(q+1)/4 ? Title: Re: Compressed keys, Y from X Post by: Zeilap on April 01, 2013, 08:26:57 PM Yep, that works, thanks a lot! Here's a sketch of why:EDIT: I still have a question: how do you know that sqrt(a) = a(q+1)/4 ? Fermat's little theorem (https://en.wikipedia.org/wiki/Fermat%27s_little_theorem) tells us that aq-1 = 1 (mod q), so by rearranging, aq-1 - 1 = 0 (mod q) which we can factorise into (a(q-1)/2 - 1)(a(q-1)/2 + 1) = 0 (mod q) These factors multiply to zero, so one of the factors must itself be zero. In particular, we must have a(q-1)/2 = -1 or +1 (mod q). Each case actually corresponds to whether the square root exists or not (1 for exists, -1 for doesn't exist). Now, let's say a = x2, so that sqrt(a) = x. Then, a(q+1)/4 = x(q+1)/2 = x(q-1)/2 + 1 = x * x(q-1)/2 = +x or -x (mod q) There's a little more work to show that the square root is unique, which is not true in general, for instance 3*3 = 1 (mod 8 ) and 1*1 = 1 (mod 8 ) So in this case, 1 has multiple square roots modulo 8. However for our q, they are unique. Title: Re: Compressed keys, Y from X Post by: piotr_n on May 01, 2013, 06:15:04 PM Sorry for maybe a stupid question, but I have a need to make a reverse operation; compress a key.
So, how do I decide whether to set 02 or 03 in front of the X? Title: Re: Compressed keys, Y from X Post by: jackjack on May 01, 2013, 09:49:20 PM 02 if Y is even, 03 if odd
Title: Re: Compressed keys, Y from X Post by: piotr_n on May 02, 2013, 08:23:16 AM 02 if Y is even, 03 if odd thanksTitle: Re: Compressed keys, Y from X Post by: kjj on May 02, 2013, 12:24:56 PM You can also think of it as 0x02+mod(Y,2)
Title: Re: Compressed keys, Y from X Post by: piotr_n on May 02, 2013, 02:10:47 PM I prefer 2+Y.Bit(0) :P
Title: Re: Compressed keys, Y from X Post by: piotr_n on May 11, 2013, 01:30:49 PM I have a slightly different question, but since there are some real math experts in this topic already, please let me ask it in here.
I need to write a function that recovers a public key from ECDSA signature. It's the algorithm described in section 4.6.1 of the SEC1 spec (http://www.secg.org/index.php?action=secg,docs_secg) - it seems simple, but I guess I am just too stupid to get it :) Let's say that we have a signature of: Code: R = E1D48751A24F0DB604C86A4706D2113FF869808522E8AF4A04F253F03EA87EF1 So, the operation I need to do first, is the equivalent of openssl's ec_GFp_simple_set_compressed_coordinates(). It takes X and the parity of Y, and returns some point R - right? From what I see the actual result, for the example inputs, should be: Code: Rx : 7E677C42747BBDEF47AFAA51001D55A82D8C2B643EF74D6E014F64DCFD31BBA0 Could anyone please tell me how to calculate this R, preferably with some example, in python or whatever..? I was trying to reverse engineer how openssl does it, but analyzing that code has not got me too far, so far... :) Also, if you could please explain me what is an "octet string" and how is it different from a big integer expressed as MSB encoded string of bytes? Title: Re: Compressed keys, Y from X Post by: jackjack on May 11, 2013, 01:38:43 PM I'm about to release a code for signing in Armory
If I understood correctly, it should solve your problem Title: Re: Compressed keys, Y from X Post by: piotr_n on May 11, 2013, 01:39:52 PM I'm about to release a code for signing in Armory OK - I'll be looking forward for it..If I understood correctly, it should solve your problem Cheers Title: Re: Compressed keys, Y from X Post by: jackjack on May 11, 2013, 02:05:58 PM In the mean time, could you post the message and address that give this signature?
It seems odd because Rx = r + {0;1}*q and this doesn't correspond to your example at all (first bits should be the same as q=0xffffffffffffffff...) For exemple, signing 'bitcoin' with private key '\x01'*32 gives Code: Flag: 1c -> uncompressed key and Rx=r+0*q It's from the top of my head, I'll post the code when I have access to my dev computer Title: Re: Compressed keys, Y from X Post by: piotr_n on May 11, 2013, 03:27:42 PM May it be because it is a signature from a testnet address?
Code: bitcoind -testnet verifymessage mqMmY5Uc6AgWoemdbRsvkpTes5hF6p5d8w "H+HUh1GiTw22BMhqRwbSET/4aYCFIuivSgTyU/A+qH7xZp5gz61zp//WMFTbpNDbiMYoYz7pD88NYg/0DekcMpY=" test Also I was giving the intermediate R - not the Q, that comes at the end. How to calc the Q - this was supposed to be my next question, because is seems to be even more screwed up :) And then, at the very end, they take the X and Y from the Q (that is already called a "public key"): Code: Q.X: 6130AE7913286EC4D8296AEB7361420C259CD11478FB24FEDA77F81E256059AA .. and turn it into an actual bitcoin public key, where: Code: X: 05eb0c4f42ecf74ab8789f2855ef33cad6ac0ec1ba6b7179578cb9f218e7793d So how much more crazy could it be? :) I spent about 6 hours today trying to figure it out, before finally deciding to seek some help on the forum. Title: Re: Compressed keys, Y from X Post by: jackjack on May 11, 2013, 03:43:11 PM I'm finishing the code, it's coming in the following hours
Here's what I get for your test: Code: fb: 1b As for Q: Q = inv_r * ( R*s + G*minus_e ) Title: Re: Compressed keys, Y from X Post by: piotr_n on May 11, 2013, 03:48:47 PM I'm finishing the code, it's coming in the following hours Yeah - that was actually my first guess, that the "Rx" should be the same as the "r", while Ry should be calculated in the same way as we calc Y from 02||X, for a compressed public key.Here's what I get for your test: Code: fb: 1b But after I put some debugs into bitcoin's key.cpp, it seems that the EC_POINT_set_compressed_coordinates_GFp that is called from there returns completely different X. Title: Re: Compressed keys, Y from X Post by: piotr_n on May 11, 2013, 04:03:01 PM At some point (in ec_GFp_simple_set_compressed_coordinates function) I do have:
Code: x: e1d48751a24f0db604c86a4706d2113ff869808522e8af4a04f253f03ea87ef1 ... but then, the function calls EC_POINT_set_affine_coordinates_GFp to "assign" these x,y values into the R - and after this the R's, x and y are: Code: Rx : 7E677C42747BBDEF47AFAA51001D55A82D8C2B643EF74D6E014F64DCFD31BBA0 Title: Re: Compressed keys, Y from X Post by: jackjack on May 11, 2013, 06:03:05 PM I don't get where those values come from...
See https://github.com/jackjack-jj/jasvet/blob/master/jasvet.py Line 361 Title: Re: Compressed keys, Y from X Post by: piotr_n on May 11, 2013, 06:26:43 PM I don't get where those values come from... Thanks! I will have a look..See https://github.com/jackjack-jj/jasvet/blob/master/jasvet.py Line 361 I was hoping that it would actually be less complicated than what I see in bitcoind+openssl :) Title: Re: Compressed keys, Y from X Post by: jackjack on May 11, 2013, 07:29:30 PM I don't find that as complicated as in bitcoin-qt
Your specific problem is only between lines 361->412. I even left the print's so you can uncomment them to see the values Just delete everything after line 530 and put this Code: verifySignature('mqMmY5Uc6AgWoemdbRsvkpTes5hF6p5d8w','H+HUh1GiTw22BMhqRwbSET/4aYCFIuivSgTyU/A+qH7xZp5gz61zp//WMFTbpNDbiMYoYz7pD88NYg/0DekcMpY=','test') Title: Re: Compressed keys, Y from X Post by: piotr_n on May 11, 2013, 07:31:06 PM Indeed, it looks cool and simple - and it works!
But can you please tell me what the "R*s" (in line 406) actually does? I mean, you have (decimals): Code: Rx = 102145896445573563625240447116654222837109247557536823325858067433615090286321 ... and R*s gives you a point having: Code: x = 112793881772482502863430761842017408792441979840968192252645857563994847441261 So how do I multiply a point by a number to get such a result? I mean, not using python.. Title: Re: Compressed keys, Y from X Post by: jackjack on May 11, 2013, 07:37:15 PM It's the ECC multiplication
You can look at lines 216->237 for algorithm To understand: http://cs.ucsb.edu/~koc/ccs130h/notes/ecdsa.pdf http://en.wikipedia.org/wiki/Elliptic_curve_cryptography http://en.wikipedia.org/wiki/Elliptic_curve etc... Title: Re: Compressed keys, Y from X Post by: piotr_n on May 11, 2013, 07:39:09 PM It's the ECC multiplication OK - thanks a lot, man!You can look at lines 216->237 for algorithm To understand: http://cs.ucsb.edu/~koc/ccs130h/notes/ecdsa.pdf http://en.wikipedia.org/wiki/Elliptic_curve_cryptography http://en.wikipedia.org/wiki/Elliptic_curve That's all I needed to know. Title: Re: Compressed keys, Y from X Post by: piotr_n on May 11, 2013, 08:15:58 PM And so it worked in my language as well. :)
https://github.com/piotrnar/gocoin/blob/master/tools/versigmsg.go Thanks again, @jackjack! Title: Re: Compressed keys, Y from X Post by: jackjack on May 11, 2013, 10:11:19 PM I'm glad that helped!
|