ECDSA: (v, r, s), what is v?

24

19

Deterministically signing a Tx with RFC6979 returns v, r, s, where r and s are the 2 values used in standard ECDSA signatures. v = 27 + (y % 2), so 27 + the parity of r, as pybitcointools indicates.

So for even r, we get v = 27, odd r we get v = 28.

How is the value of v (27 or 28) important? Why is it necessary to have a v value? Also, why is it 27?

Wizard Of Ozzie

Posted 2015-07-01T09:28:27.847

Reputation: 4 535

2Seems to be some sort of a version byte, similar to the version byte used in encoding addresses. Not sure of the significance of 27/28.morsecoder 2015-07-01T15:04:11.540

Your link to github is broken; I would fix it but apparently I need to change at least 6 characters for it to be a valid edit.David Grayson 2015-07-01T16:41:38.593

@DavidGrayson Link fixed. Perhaps Peter Wuille can comment, as I believe I've read that 27 was chosen arbitrarily because it was "halfway" between used version byte choices, though I can't find that source for the life of meWizard Of Ozzie 2015-07-01T19:55:36.420

4That's correct. It was an arbitrary choice for a number at the time, because we needed a byte to convey public key recovery information. I'll try to write a full answer later.Pieter Wuille 2015-07-02T11:37:16.987

Answers

32

This has nothing to do with RFC6979, but with ECDSA signing and public key recovery.

The (r, s) is the normal output of an ECDSA signature, where r is computed as the X coordinate of a point R, modulo the curve order n.

In Bitcoin, for message signatures, we use a trick called public key recovery. The fact is that if you have the full R point (not just its X coordinate) and s, and a message, you can compute for which public key this would be a valid signature. What this allows is to 'verify' a message with an address, without needing to know the full key (we just do public key recovery on the signature, and then hash the recovered key and compare it with the address).

However, this means we need the full R coordinates. There can be up to 4 different points with a given "X coordinate modulo n". (2 because each X coordinate has two possible Y coordinates, and 2 because r+n may still be a valid X coordinate). That number between 0 and 3 we call the recovery id, or recid. Therefore, we return an extra byte, which also functions as a header byte, by using 27+recid (for uncompressed recovered pubkeys) or 31+recid (for compressed recovered pubkeys).

Strictly speaking the recid is not necessary, as we can just cycle through all the possible coordinate pairs and check if any of them match the signature. The recid just speeds up this verification.

In general, if h is the cofactor, the maximum number of different points with given "X coordinate modulo n" will be 2(h+1). In the case of secp256k1, which has cofactor 1, we get 2(1+1) = 4.

Pieter Wuille

Posted 2015-07-01T09:28:27.847

Reputation: 54 032

Can you link to the code which implements this? I'm going to start learning C++ using functions like this which I understandWizard Of Ozzie 2015-08-01T06:21:04.363

The signing code is in libsecp256k1, which also has verification code, but that is not currently used. For verification, there is C code in Bitcoin Core (see pubkey.cpp) which does a series of OpenSSL calls to do the bulk of the work. I am not sure that reading cryptographic C code is the best way to learn C++ :)Pieter Wuille 2015-08-01T09:42:03.893

It's more a way of learning things I understand pretty well already, and am interested in. I've learned Python that way and the ultimate goal is to know the core software tooWizard Of Ozzie 2015-08-02T09:00:43.053

4@PeterWuille There can be up to 4 different points with a given "X coordinate modulo n". (2 because each X coordinate has two possible Y coordinates, and 2 because r+n may still be a valid X coordinate). I understand the former (2 y values for each x, because of the symmetry)... But how does the latter work? ie r+n may still be a valid X coordinate??Wizard Of Ozzie 2015-08-18T12:20:16.793

6X and Y coordinates are numbers modulo p, the field size, which is around 2^256 - 2^32 for secp256k1. The value r and s in the signature however are modulo n, the group order, which is around 2^256 - 2^128. When R.x is between n and p, r is reduced to R.x-n. Thus, if you have an r value below 2^128-2^32, there may be 2 valid R.x values corresponding to it.Pieter Wuille 2015-08-18T12:26:22.300

@PieterWuille - Is this specific for secp2561k, or can this be generalized for all elliptic curve signatures? Also, how does it relate to this answer on crypto SE - https://crypto.stackexchange.com/questions/18105/how-does-recovering-the-public-key-from-an-ecdsa-signature-work ?

Karel Bílek 2017-10-27T18:28:42.080

ECDSA always supports public key, regardless of the curve. For curves with cofactor > 1 it is slightly more complicated. That linked answer explains the procedure.Pieter Wuille 2017-10-27T21:00:04.480

Which, please, of the 4 possible output (27..30) corresponds to which of the possible results. Eg: 0 = positive Y and X1? where is this documented?Sentinel 2018-01-10T15:09:38.837

2

@Sentinel You can get full information on the recovery method here: http://www.secg.org/sec1-v2.pdf

Souza 2018-02-10T00:14:28.493

527 = lower X even Y. 28 = lower X odd Y. 29 = higher X even Y. 30 = higher X odd Y. Note that 29 and 30 are exceedingly rarely, and will in practice only ever be seen in specifically generated examples. There are only two possible X values if r is between 1 and (p mod n), which has a chance of about 0.000000000000000000000000000000000000373 % to happen randomly.Pieter Wuille 2018-02-10T00:19:22.213

2@Souza / Pieter - Thanks. I had already managed to discover the answer to that - it took me forever! I did actually find that ASN.1 in sec1-v2.pdf after an enormous amount of digging. When I found it, I thought I'd struck gold. The problem is that the Ethereum documentation (I am implementing an Ethereum light client) does not include detailed protocol info, and official implementations tend to rely on libraries that go where Bitcoin already trod, so details like the 'v' parameter are lost/buried in very, very obscure code.Sentinel 2018-02-10T11:42:22.937

1@Sentinel my strugle's the same. I am working on top of Ethereum's protocol and they say little to nothing about this. And you're right, they both use libsecp256k1.Souza 2018-02-10T16:04:22.673

1@Souza - agreed. It is a struggle. I am trying to contact Ethereum foundation to put together accessible protocol documentation and get funding to do it. I am putting together a light client using reactive extensions and .NET, where I am treating all protocol messages as streams flowing through stack-layer adapters, and trying to insulate the top level protocol from lower level differences (discv4 vs v5 etc for example). By the time I am done I should be able to write a book on it.Sentinel 2018-02-11T15:18:03.863

2

I don't think that the v you describe is part of RFC6979 because I cannot find it in that document. This v happens to be part of the ecdsa_raw_sign raw sign function in pybitcointools, which calls deterministic_generate_k, which is an implementation of RFC6979.

RFC6979 just helps you generate a deterministic k value for signing. It does not help you generate r and s. To generate r and s, you just use the normal ECDSA algorithm; you don't have to refer to RFC6979 after you have used it to generate k. RFC6979 generates k, which is an input to the signing algorithm that can generate r and s.

David Grayson

Posted 2015-07-01T09:28:27.847

Reputation: 561

Right, but does v appear across implementations? Pybitcointools isn't the only implementation to use it, I believe.Wizard Of Ozzie 2015-07-02T00:42:13.057

The only other implementation I have seen is libsecp256k1, which does not return a v number. That library provides a function named secp256k1_nonce_function_rfc6979 whose only output is a 32-byte buffer of data.

David Grayson 2015-07-02T01:33:13.580

2secp256k1_ecdsa_sign_compact (old API) or secp256k1_pubkey_serialize_compact (new API) do return the recovery id (the value v, but without the 27 constant term). See my answer.Pieter Wuille 2015-07-31T23:10:41.360

Yeah, so v has to do with signing, not RFC6979.David Grayson 2015-08-01T00:47:42.760

@DavidGrayson yeah, have amended title :)Wizard Of Ozzie 2015-08-01T11:04:26.493

0

v is needed to recover the public key. As a result of recovering the public key from ECDSA signature, 0, 1, or 2 points can be returned. In order to strictly indicate which point corresponds to the "original" public key, an additional byte is used

viktor32

Posted 2015-07-01T09:28:27.847

Reputation: 1