OpenSSL cannot verify ECDSA signature C++, C# verifies correctly -


i passing in following(the digest/hash sha1):

hash = hextobytes("9e712647173b435cf691537a76c2f1423e4a18ed"); signature = base64tobytes("aslq3wgusdkjcffwe3kvbfp7bdnjdajl2ezietr6dsiacfvasveaw9v6s3im0lnaqav2bte7ebcrmef/qb2/hw=="); pubkey16 = "04c2d0a868c35f475208b6c33a58d4ac275190f1a9d5804456ff07c42605716ef748fb4fd246163e851dbe9a942569741f54341a7c85f394b20777ab7fe526096a";//actual key lacks 04 @ front i'm guessing openssl needs this? 

to function:

    int misc::verify_signature(unsigned char* hash, std::vector<unsigned char> signature, char* cpubkey16) {          printf("signature length: %d\n", signature.size());          int function_status = -1;          ec_key    *eckey = null;         ec_point *pub_key;         const ec_group *ecgroup;          ssl_library_init();         ssl_load_error_strings();          std::string pubkeys(cpubkey16);          std::vector<unsigned char> pubkeyvc = misc::hextobytes(pubkeys);          const unsigned char* pubkeyvcp = pubkeyvc.data();          const unsigned char** pubkeyvcpp = &pubkeyvcp;          //nid_secp256k1 not r1 .net uses         eckey = ec_key_new_by_curve_name(nid_x9_62_prime256v1);          //load our public key         eckey = o2i_ecpublickey(&eckey, pubkeyvcpp, pubkeyvc.size());          if (!ec_key_check_key(eckey)) {             printf("ec_key_check_key failed:\n");             printf("%s\n", err_error_string(err_get_error(), null));         }         else {             printf("public key verified ok\n");         }          //create formatted signature         ecdsa_sig* ec_sig = ecdsa_sig_new();          //split signature r , s value          //set r         if (null == bn_bin2bn(&signature[0], 32, (ec_sig->r))) {             printf("failed set r value in ec signature\n");             function_status = -1;         }         printf("post r  :%s\n", bn_bn2hex(ec_sig->r));          //set s         if (null == bn_bin2bn(&signature[0] + 32, 32, (ec_sig->s))) {             printf("failed set s value in ec signature\n");             function_status = -1;         }         printf("post s  :%s\n", bn_bn2hex(ec_sig->s));          //encode signature         int sig_size = i2d_ecdsa_sig(ec_sig, null);         unsigned char *sig_bytes =(unsigned char *) malloc(sig_size);         unsigned char *p;          printf("orig sig size: %d\n", sig_size);          p = sig_bytes;         int new_sig_size = i2d_ecdsa_sig(ec_sig, &p);          printf("new sig size: %d\n", new_sig_size);          int verify_status = ecdsa_do_verify(hash, 20, ec_sig, eckey);          printf("verify status: %d\n", verify_status);          const int verify_success = 1;         if (verify_success != verify_status)         {             if(verify_status==-1)handleerrors();             printf("failed verify ec signature\n");             function_status = -1;         }         else         {             printf("verifed ec signature\n");             function_status = 1;         }          //ec_group_free(ecgroup);//might fail ecgroup constant todo         ec_key_free(eckey);          return function_status;     } 

but cannot verify signature in openssl(verify_success 0), though exact same data verifies in c#.

any ideas why or doing wrong?

the public key in c# is:

4543533120000000c2d0a868c35f475208b6c33a58d4ac275190f1a9d5804456ff07c42605716ef748fb4fd246163e851dbe9a942569741f54341a7c85f394b20777ab7fe526096a 

i'm assuming 4543533120000000 .net specific stuff pre-pended 04 rest of it.

here c# code used verify signature , successfully(sha1 of databytes identical across both programs)..

        hashalgorithm hashman2 = new sha1managed();          byte[] databytes = hashman2.computehash(encoding.ascii.getbytes("h4siaaaaaaaeadpqmqbcqzbjdssm0xcmdtfuyypqajfnaisaaovfht3raaaa"));          string sig = "aslq3wgusdkjcffwe3kvbfp7bdnjdajl2ezietr6dsiacfvasveaw9v6s3im0lnaqav2bte7ebcrmef/qb2/hw==";          byte[] readpublickey2 = convert.frombase64string("runtmsaaaadc0khow19hugi2wzpy1kwnuzdxqdwarfb/b8qmbxfu90j7t9jgfj6fhb6alcvpdb9unbp8hfousgd3q3/ljglq");          console.writeline("public key file read as:");         console.writeline(convert.tobase64string(readpublickey2));          using (ecdsacng ecsdkey = new ecdsacng(cngkey.import(readpublickey2, cngkeyblobformat.eccpublicblob)))         {             if (ecsdkey.verifydata(databytes, convert.frombase64string(sig)))             {                 console.writeline("data , signature have been verified.");             }             else             {                 console.writeline("data , signature not verified!");             }         } 

any appreciated.

i found issue, using .net function ecdsa.signdata, hashes data prior input(with ecdsacng.hashalgorithm), assuming taking hash input correct function ecdsa.signhash, i've switched signhash , new signature/message verifies correctly. (note may different depending on version of .net, sure check api version)

in case someone, here draft-working function(there extra/unneeded stuff in here may you):

    int misc::verify_signature(std::vector<unsigned char> hash, std::vector<unsigned char> signature, char* cpubkey16) {          printf("signature length: %d\n", signature.size());          int function_status = -1;          ec_key    *eckey = null;         ec_point *pub_key;         const ec_group *ecgroup;          ssl_library_init();         ssl_load_error_strings();          std::string pubkeys(cpubkey16);          std::vector<unsigned char> pubkeyvc = misc::hextobytes(pubkeys);          printf("raw pubkey bytes: \n");         (unsigned char t : pubkeyvc) {             printf("%d\n", t);         }         printf("raw pubkey length:%d \n", pubkeyvc.size());          const unsigned char* pubkeyvcp = pubkeyvc.data();          const unsigned char** pubkeyvcpp = &pubkeyvcp;          //nid_secp256k1 not r1 .net uses         eckey = ec_key_new_by_curve_name(nid_x9_62_prime256v1);          ec_key_set_asn1_flag(eckey, openssl_ec_named_curve);          eckey = o2i_ecpublickey(&eckey, pubkeyvcpp, pubkeyvc.size());          if (!ec_key_check_key(eckey)) {             printf("ec_key_check_key failed:\n");             printf("%s\n", err_error_string(err_get_error(), null));         }         else {             printf("public key verified ok\n");         }          //create formatted signature         ecdsa_sig* ec_sig = ecdsa_sig_new();          //split signature r , s value          //set r         if (null == bn_bin2bn(&signature[0], 32, (ec_sig->r))) {             printf("failed set r value in ec signature\n");             function_status = -1;         }         printf("post r  :%s\n", bn_bn2hex(ec_sig->r));          ////try pad s         //std::vector<unsigned char> spadded = std::vector<unsigned char>(&signature[32], &signature[32] + 32);          //spadded.insert(spadded.begin(), '0');         //spadded.insert(spadded.begin(), '0');          //set s         if (null == bn_bin2bn(&signature[32], 32, (ec_sig->s))) {             printf("failed set s value in ec signature\n");             function_status = -1;         }         printf("post s  :%s\n", bn_bn2hex(ec_sig->s));            //encode signature         std::vector<unsigned char> rvalue = std::vector<unsigned char>(&signature[0], &signature[0] + 32);         std::vector<unsigned char> svalue = std::vector<unsigned char>(&signature[32], &signature[32] + 32);          std::vector<unsigned char> derencoded = std::vector<unsigned char>();          derencoded.push_back(0x30);         //push payload length position later          //seperator         derencoded.push_back(0x02);          //length of rvalue         if (rvalue.at(0) >= 0x80) {             derencoded.push_back(rvalue.size() + 1);         }         else {             derencoded.push_back(rvalue.size());         }          //push rvalue bytes in         int c = 0;         (unsigned char b : rvalue) {             if (b >= 0x80 && c == 0) {                 derencoded.push_back(0);             }             derencoded.push_back(b);             c++;         }          //seperator         derencoded.push_back(0x02);         //length of svalue         if (svalue.at(0) >= 0x80) {             derencoded.push_back(svalue.size() + 1);         }         else {             derencoded.push_back(svalue.size());         }          //push svalue bytes in         c = 0;         (unsigned char b : svalue) {             if (b >= 0x80 && c == 0) {                 derencoded.push_back(0);             }             derencoded.push_back(b);             c++;         }          //insert payload length in          int len = derencoded.size() - 1;          derencoded.insert(derencoded.begin() + 1, len);          printf("encoded sig len: %d\n", derencoded.size());          printf("encoded sig64: %s\n", misc::base64_encode_d(&derencoded).c_str());          //unsigned char *p = (unsigned char*)malloc(ecdsa_size(eckey));          //int new_sig_size = i2d_ecdsa_sig(ec_sig, &p);          //printf("new sig size: %d\n", new_sig_size);          //for (int x = 0; x < new_sig_size; x++) {         //  printf("%d\n", p[x]);         //}          //dump der encoded sig         //printf("der encoded signature\n");         //const unsigned char* pp = (unsigned char*) malloc(new_sig_size);         //d2i_ecdsa_sig(&ec_sig, &pp, new_sig_size);         //std::vector<unsigned char> ppvc = std::vector<unsigned char>(pp, pp+new_sig_size);          //printf("base64: %s\n", misc::base64_encode_d(&ppvc).c_str());          //ecdsa_sig *signature = ecdsa_do_sign(hash, 20, eckey);         //ecdsa_size(eckey);          int verify_status = ecdsa_verify(0, hash.data(), hash.size(), derencoded.data(), derencoded.size(), eckey);//ecdsa_do_verify(hash.data(), hash.size(), ec_sig, eckey);          printf("verify status: %d\n", verify_status);          const int verify_success = 1;         if (verify_success != verify_status)         {             if (verify_status == -1)             {                 handleerrors();             }             printf("failed verify ec signature\n");             function_status = -1;         }         else         {             printf("verifed ec signature\n");             function_status = 1;         }          //ec_group_free(ecgroup);//might fail ecgroup constant todo         ec_key_free(eckey);          return function_status;     } 

Comments