Bitcoin Forum
May 03, 2024, 03:03:52 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
  Home Help Search Login Register More  
  Show Posts
Pages: [1]
1  Bitcoin / Development & Technical Discussion / Re: How does "recid" variable work in libspec256k1 library? on: July 09, 2020, 08:16:33 AM
Thanks to your kind instruction again, and I'm sorry for late reply.

According to your advice about the conversion "Higher sign-s" to "Lower sign-s", I could calculate appropriate sign-s without retry, and it was able to be used for Ethereum communication.
I had a deeper understanding of it, so I could also optimize some process flows .

Thank you for your continued support.
2  Bitcoin / Development & Technical Discussion / Re: How does "recid" variable work in libspec256k1 library? on: June 01, 2020, 10:57:42 AM
Thanks to your kind instruction.

I still don't understand, but result of various trials, I could get the correct "recid" from "sign r", "sign s" and  "original public key", in the following process,

Step 1. Make sign data by an ECDSA signing function.
  (It is not included in libsecp256k1. A third party provided one, so it is not arranged for Bit Coin and it doesn't output "recid".)
Step 2. Recover public-key from "sign r", "sign s" and "recid = 0" with secp256k1_ecdsa_recover function.
Step 3. Compare the recovered public-key with original public-key.
Step 4. If they are matched, recid = 0. If not matched, recid = 1.
  (According to some articles for Ethereum, I assumed recid is 0 or 1.)

Then I made transaction data from above result and sent it to the Brock Chain (Ethereum) built on cloud for my test, but often error messages were sent back.
When I executed the verify function of libsecp256k1 for the transaction data going to send, I found that when the validation function returned an error, the Brock Chain also sent an error message back.
Strictly speaking, if sign-s is "higher than the group order divided by 2" (quoted from the commnet in libsecp256k1, secp256k1_scalar_is_high function), the Block Chain will sent an error message back.

So I added range check for sign-s with secp256k1_scalar_is_high function, and if it is "higher", signing process will be retried until the "sign-s" will become "not higher".

It works and the Brock Chain no longer returns errors.

From these results, I assumed as follows,
1. Comparation of public keys determine that it is "even Y" or "odd Y".
2. Higher "sign-s" is not allowed for Etherium.
  (I don't understant about it.
   Maybe, the "third party signing function" doesn't avoid overflowed Rx, so it generates the "sign-s" values corresponding to recid = 2 or 3?)

In any case, apparently I found that it is possible to identify the "recid" from "sign-r", "sign-s" and "original public key".

Thank you again.
3  Bitcoin / Development & Technical Discussion / How does "recid" variable work in libspec256k1 library? on: May 19, 2020, 05:04:26 PM
I'm trying to understand how does "recid" (Recovery ID) variable work in libspec256k1 library (with C language).
(https://github.com/bitcoin-core/secp256k1)
I'm sorry if my question was too primitive or inappropriate on this forum.
I would appreciate any advice on the correct sites, the correct forums or etc.

I'd like to understand the relationship between "recid" (Recovery ID) , recovered-public-key and verification, so I tried following steps with modifying "secp256k1_ecdsa_sign_recoverable" function in  main_impl.h.

Step1: Original signing operation. (no modification)
I use "secp256k1_ecdsa_sign_recoverable" function in main_impl.h to get recoverable signature.
In that function, "secp256k1_ecdsa_sig_sign" function is called and it returns "sign" and "recid".

Step2: Recover public key with recid, and verify.
I wanted to get the recovered public-key using "recid", which was given by "secp256k1_ecdsa_sig_sign function" in Step 1, and to verify the signed data.
I got the recovered public-key from "secp256k1_ecdsa_recover" function, and it returned the result "1 (recovery success)".
Then "secp256k1_ecdsa_verify" function returned the result "1 (verification success)".

Step3: Expect "verification failure" with wrong "recid", but...
I tried the public-key recovery with wrong "recid", and expected that verification failed.
"recid" range is 0 to 3, but actually in this experiment, the "recid" value output by the secp256k1_ecdsa_sig_sign function was 0 or 1.
So, if "recid" was 0, I intentionally changed it to 1, and if it was 0, changed to 1.
I got the recovered public-key from "secp256k1_ecdsa_recover" function with wrong "recid", and it returned the result "1 (recovery success)".
Then "secp256k1_ecdsa_verify" function returned the result "1 (verification success)", even though used public-key was recovered with wrong "recid".

Why verification succeeded with the public-key recovered with wrong "recid"?

The reason why I want to do something like Step3 is that I am strongly considering an experiment using a signature function of another library instead of secp256k1_ecdsa_sig_sign of libspec256k1 as a signature function.
The alternative signature function is designed only for ECDSA signatures, so it does not output "recid".
Also, its implementation is completely hidden along with the private-key, and it is not possible to retrieve the value in the internal calculation process.
But I need "recid" to construct appropriate blockchain transaction data to send, so I considered Step3 sequence.

Sorry for the long sentence.
Thank you.

-----------------
Following is overview of my code at each step.
(It's a little simplified.)

Step1 original "secp256k1_ecdsa_sign_recoverable" basic process is
Code:
<... some processes ...>
/* Convert some input arguments of "secp256k1_ecdsa_sign_recoverable" into the "secp256k1_scalar type" to be used for signing  function. */
secp256k1_scalar sec, non, msg;
secp256k1_scalar_set_b32(&sec, seckey, &overflow);  /* Secret-key "seckey" was converted into "&sec" */
secp256k1_scalar_set_b32(&msg, msg32, NULL);        /* Hash "msg32", which was created from original message data, was converted into "&msg" */
secp256k1_scalar_set_b32(&non, nonce32, &overflow); /* Nonce data "nonce32" was converted into "&non" */
<... some processes ...>
/* make "sign" and "recid" as following*/
secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid);
/* "&r" and "&s" are ouput sign-r and sign-s. "recid" is ouput recovery id (0, 1, 2 or 3). The others are given from the input arguments of "secp256k1_ecdsa_sign_recoverable". "ctx" (secp256k1 context object) was created for signing and verification. */
<... some processes ...>
/* Combine "sign"s and "recid". It will be decomposed into "sign"s and "recid" again by higher processing, and they will be used to construct bitcoin transaction data.
secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid);
/* "signature" is ouput recoverable-signature-data ("secp256k1_ecdsa_recoverable_signature" type), which is consisting of the inputs "&r", "&s", and "recid". It is also the output of "secp256k1_ecdsa_sign_recoverable" function. */

Step2 modified "secp256k1_ecdsa_sign_recoverable" basic process is
Code:
<... some processes ...>
/* Convert some input arguments of "secp256k1_ecdsa_sign_recoverable" into the "secp256k1_scalar type" to be used for signing  function. */
secp256k1_scalar sec, non, msg;
secp256k1_scalar_set_b32(&sec, seckey, &overflow);  /* Secret-key "seckey" was converted into "&sec" */
secp256k1_scalar_set_b32(&msg, msg32, NULL);        /* Hash "msg32", which was created from original message data, was converted into "&msg" */
secp256k1_scalar_set_b32(&non, nonce32, &overflow); /* Nonce data "nonce32" was converted into "&non" */
<... some processes ...>
/* make "sign" and "recid" as following*/
secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid);
/* "&r" and "&s" are ouput sign-r and sign-s. "recid" is ouput recovery id (0, 1, 2 or 3). The others are given from the input arguments of "secp256k1_ecdsa_sign_recoverable". "ctx" (secp256k1 context object) was created for signing and verification. */
<... some processes ...>
/* Combine "sign"s and "recid". It will be decomposed into "sign"s and "recid" again by higher processing, and they will be used to construct bitcoin transaction data.
secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid);
/* "signature" is ouput recoverable-signature-data ("secp256k1_ecdsa_recoverable_signature" type), which is consisting of the inputs "&r", "&s", and "recid". It is also the output of "secp256k1_ecdsa_sign_recoverable" function. */
/*****************************************/
/**** Step2 Added: Recover public-key ****/
/*****************************************/
int res_pubkey_recover;
static secp256k1_pubkey pubkey_buf;
res_pubkey_recover = secp256k1_ecdsa_recover(ctx, &pubkey_buf, signature, msg32);
/* "&pubkey_buf" is output recovered public key. "signature" is input, which has "sign"s and "recid". "msg32" is the hash created from original message data (given as a input argument of "secp256k1_ecdsa_sign_recoverable") */
/*****************************************/
/**** Step2 Added: Verify signed data ****/
/*****************************************/
int res_sig_conv;
static secp256k1_ecdsa_signature normal_sig_buf;
/* Convert recoverable-signature-data into normal-type-signature-data to be used for verification function.
res_sig_conv = secp256k1_ecdsa_recoverable_signature_convert(ctx, &normal_sig_buf, signature);
/* "&normal_sig_buf" is output converted signature data. "res_sig_conv" is always 1. */
/* Verification */
int res_verify;
res_verify = secp256k1_ecdsa_verify(ctx, &normal_sig_buf, msg32, &pubkey_buf);
/* "res_verify = 1" is verification success. "res_verify = 0" is verification failure. */

Step3 modified "secp256k1_ecdsa_sign_recoverable" basic process is
Code:
<... some processes ...>
/* Convert some input arguments of "secp256k1_ecdsa_sign_recoverable" into the "secp256k1_scalar type" to be used for signing  function. */
secp256k1_scalar sec, non, msg;
secp256k1_scalar_set_b32(&sec, seckey, &overflow);  /* Secret-key "seckey" was converted into "&sec" */
secp256k1_scalar_set_b32(&msg, msg32, NULL);        /* Hash "msg32", which was created from original message data, was converted into "&msg" */
secp256k1_scalar_set_b32(&non, nonce32, &overflow); /* Nonce data "nonce32" was converted into "&non" */
<... some processes ...>
/* make "sign" and "recid" as following*/
secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid);
/* "&r" and "&s" are ouput sign-r and sign-s. "recid" is ouput recovery id (0, 1, 2 or 3). The others are given from the input arguments of "secp256k1_ecdsa_sign_recoverable". "ctx" (secp256k1 context object) was created for signing and verification. */
<... some processes ...>
/* Combine "sign"s and "recid". It will be decomposed into "sign"s and "recid" again by higher processing, and they will be used to construct bitcoin transaction data.
/**************************************/
/**** Step3 Added: Use wrong recid ****/
/**************************************/
recid = (recid == 0 ? 1 : 0); /* Intentionally use wrong recid. */
secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid);
/* "signature" is ouput recoverable-signature-data ("secp256k1_ecdsa_recoverable_signature" type), which is consisting of the inputs "&r", "&s", and "recid". It is also the output of "secp256k1_ecdsa_sign_recoverable" function. */
/*****************************************/
/**** Step2 Added: Recover public-key ****/
/*****************************************/
int res_pubkey_recover;
static secp256k1_pubkey pubkey_buf;
res_pubkey_recover = secp256k1_ecdsa_recover(ctx, &pubkey_buf, signature, msg32);
/* "&pubkey_buf" is output recovered public key. "signature" is input, which has "sign"s and "recid". "msg32" is the hash created from original message data (given as a input argument of "secp256k1_ecdsa_sign_recoverable") */
/*****************************************/
/**** Step2 Added: Verify signed data ****/
/*****************************************/
int res_sig_conv;
static secp256k1_ecdsa_signature normal_sig_buf;
/* Convert recoverable-signature-data into normal-type-signature-data to be used for verification function.
res_sig_conv = secp256k1_ecdsa_recoverable_signature_convert(ctx, &normal_sig_buf, signature);
/* "&normal_sig_buf" is output converted signature data. "res_sig_conv" is always 1. */
/* Verification */
int res_verify;
res_verify = secp256k1_ecdsa_verify(ctx, &normal_sig_buf, msg32, &pubkey_buf);
/* "res_verify = 1" is verification success. "res_verify = 0" is verification failure. */
Pages: [1]
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!