How can I download random OpenSSL data for use in an ECDSA subscription?

I want to submit special OpenSSL data for use as random seeds when signing data using an EC key. I am doing this to compare my application with another reference (closed source). This utility accepts a file with a private key, a file with data for signing, and a file with random data as parameters.

I have EC key generation and data signing down, but I can not compare these two applications, since I have no common grounds. OpenSSL generates random data used when signing data (possibly from / dev / random) and thus gives me a different signature for each run.

I tried RAND_clear() in combination with RAND_add() , but constantly changing signatures. Either I do not understand the whole concept of ECDSA, or I'm doing something wrong.

My second option for comparing applications is to import the public key and verify the signature generated by the help program. This is the best option, but I cannot import this example of a public key (83 characters of a hexadecimal string). EC_POINT_oct2point() continues to give me null results.

Any recommendations / pointers / links are welcome.

 char * key_as_binary_data; //369368AF243193D001E39CE76BB1D5DA08A9BC0A63307AB352338E5EA5C0E05A0C2531866F3E3C2702 int data_size; //Size of the key buffer EC_POINT * ecpoint = NULL; EC_GROUP * ecgroup = NULL; EC_KEY * eckey = NULL; point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; int asn1_flag = OPENSSL_EC_NAMED_CURVE; eckey = EC_KEY_new(); ecpoint = EC_POINT_new(ecgroup); ecgroup = EC_GROUP_new_by_curve_name(OBJ_sn2nid("sect163k1")); EC_GROUP_set_asn1_flag(ecgroup, asn1_flag); EC_GROUP_set_point_conversion_form(ecgroup, form); EC_KEY_set_group(eckey,ecgroup); EC_KEY_generate_key(eckey); //This gives me a null ecpoint EC_POINT_oct2point(ecgroup,ecpoint,key_as_binary_data,data_size-1,ctx); EC_KEY_set_public_key(eckey,ecpoint); 
+2
source share
5 answers

Here is how you should load this public key:

  EC_KEY *key = NULL; EC_POINT *pub_key; const EC_GROUP *group; SSL_library_init(); SSL_load_error_strings(); key = EC_KEY_new_by_curve_name(NID_sect163k1); group = EC_KEY_get0_group(key); pub_key = EC_POINT_new(group); EC_POINT_hex2point(group, "369368AF243193D001E39CE76BB1D5DA08A9BC0A63307AB352338E5EA5C0E05A0C2531866F3E3C2702", pub_key, NULL); EC_KEY_set_public_key(key, pub_key); if (!EC_KEY_check_key(key)) { printf("EC_KEY_check_key failed:\n"); printf("%s\n",ERR_error_string(ERR_get_error(),NULL)); } else { printf("Public key verified OK\n"); } 

It seems to be checking OK, so it should work to verify the signature.

I think your error may have just passed NULL (in ecgroup) to EC_POINT_new ().

+2
source

The reason you get different results, despite the fact that you clear the pool and reload it, is that by default the implementation of OpenSSL RAND will lead to hashing pid in the output block (precisely so that even applications using one and same seed, get the same PRNG output, since 99.9% of the time that happens is Bad Thing).

Furthermore, even if it is not, it is unlikely that your reference application will use the same PRNG as OpenSSL to turn the source file into a sequence of random bytes. (If your referenced application actually also uses OpenSSL, of course). What you need to do is first find out which PRNG uses the reference application - it could be a standard PRNG design like X9.31 or FIPS-186, or it could be something completely custom. Then redefine this project for OpenSSL and connect it through RAND_set_rand_method .

As for the check: it looks like you need to transpose the lines:

  ecpoint = EC_POINT_new(ecgroup); ecgroup = EC_GROUP_new_by_curve_name(OBJ_sn2nid("sect163k1")); 

Otherwise, ecpoint is set to NULL from the very beginning, and this leads to an EC_KEY_generate_key error, because the group is set to NULL. Quote from openssl-0.9.8k crypto / ec / ec_key.c:

 if (!eckey || !eckey->group) { ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); return 0; } 
+2
source

You can manage the random data that OpenSSL creates at the time of signing using the method:

ECDSA_SIG* ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen, const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey);

where kinv is a random number that is used during signing.

+1
source

The signing procedure is solely to allow someone else to confirm that you signed it, i.e. it was your secret key that was used to sign the message (or any data) without actually having your private key.

The algorithm is described in wikipedia Elliptic_Curve_DSA Reading "Signature Generation Algorithm" shows that random data is used to help the strength of the signature and make it harder to attack to find out the private key.

Therefore, you should expect that the signature will be different every time, since it is not just a hash.

See the Signature Verification Algorithm section to verify that the verification steps are the ones you want to use to confirm that your version of openssl outputs valid signatures to the wrt method of ECDSA and the closed source program.

0
source

I can not find the documents for RAND_clear , so I can not comment on why this does not lead to reproducible random numbers.

But even if you do, what you want may not be possible. ECDSA signature generation requires the selection of a random integer in a certain range. In two different implementations of the algorithm, there can be completely different ideas about how to generate such an integer from their source of entropy. AFAIK means the conversion of entropy bits to the required number is not part of the ECDSA algorithm.

So for example (very bad examples, of course), one implementation can do this:

 int random_number = rand() % n; 

and another can do this:

 int random_number = (rand() * n) / RAND_MAX; 

That way, even if you give them the same seed data, you can still get different signatures from different implementations. All you can do is check if you have created a valid signature.

0
source

Source: https://habr.com/ru/post/1434889/


All Articles