48

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?

4
  • 2
    Seems 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
    Jul 1, 2015 at 15:04
  • 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. Jul 1, 2015 at 16:41
  • @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 me Jul 1, 2015 at 19:55
  • 4
    That'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. Jul 2, 2015 at 11:37

4 Answers 4

54

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.

13
  • 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?? Aug 18, 2015 at 12:20
  • 7
    X 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. Aug 18, 2015 at 12:26
  • 3
    @Sentinel You can get full information on the recovery method here: secg.org/sec1-v2.pdf
    – Souza
    Feb 10, 2018 at 0:14
  • 6
    27 = 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. Feb 10, 2018 at 0:19
  • 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
    Feb 10, 2018 at 11:42
6

As all the other answers already outline: v is required to recover the correct public key for a signature because there are sometimes (even with low probability) more than one valid public key to be retrieved by a signature.

Here's a cheat sheet:

  • 27 uncompressed public key, y-parity 0, magnitude of x lower than the curve order
  • 28 uncompressed public key, y-parity 1, magnitude of x lower than the curve order
  • 29 uncompressed public key, y-parity 0, magnitude of x greater than the curve order
  • 30 uncompressed public key, y-parity 1, magnitude of x greater than the curve order
  • 31 compressed public key, y-parity 0, magnitude of x lower than the curve order
  • 32 compressed public key, y-parity 1, magnitude of x lower than the curve order
  • 33 compressed public key, y-parity 0, magnitude of x greater than the curve order
  • 34 compressed public key, y-parity 1, magnitude of x greater than the curve order

For any v >= 35 you might be dealing with Ethereum signatures as per EIP-155:

v = recovery_id + CHAIN_ID * 2 + 35
3

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.

5
  • Right, but does v appear across implementations? Pybitcointools isn't the only implementation to use it, I believe. Jul 2, 2015 at 0:42
  • 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. Jul 2, 2015 at 1:33
  • 2
    secp256k1_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. Jul 31, 2015 at 23:10
  • Yeah, so v has to do with signing, not RFC6979. Aug 1, 2015 at 0:47
  • @DavidGrayson yeah, have amended title :) Aug 1, 2015 at 11:04
1

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.