I have a software system where signing ETH transactions happens in a black box. I give the information required, and it returns to me a DER-signature (30|totalLen|02|lenR|R|02|lenS|S).
Now I'm aware of the signature V value, which for EIP-155 transactions used to be the recId + (2 * chainId + 35)
. I determined this using web3.js and @ethereumjs/tx libraries with the following piece of code:
const ethAddress = '0x123ba3f3.....3a4f1d8';
ethjsTx.v = recId + 35 + 2 * chainId;
const rawTx = ethjsTx.serialize().toString(16);
const recoveredAddress = this.web3.accounts.recoverTransaction(rawTx);
return recoveredAddress === ethAddress;
I just repeat this for 2 different recId
values (0,1) until it returns true, and then I'll know the V-value.
For EIP-1559, the chainId is no longer relevant to the V value. V is simply the Y-parity of the signature. Now my question is how to find out this Y-value from a DER signature.
In this repository @line 290:
https://github.com/ethereum/go-ethereum/blob/master/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h
is the following code:
if (recid) {
/* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log
* of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria.
*/
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
}
They check whether r.y is odd, which is the value I need. Problem is, my R is a 32-byte hexadecimal, whereas in that code, r is an object with a separate y property. Is there any way to obtain this Y-value from my hexadecimal R string?