C语言 在 OpenSSL 中使用 ECDSA 对消息进行签名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2228860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:25:44  来源:igfitidea点击:

Signing a message using ECDSA in OpenSSL

cencryptionopensslelliptic-curve

提问by Anvar

How do I set the private key for signing messages when using ECDSA in OpenSSL programmatically? I have the following code:

以编程方式在 OpenSSL 中使用 ECDSA 时,如何设置用于签名消息的私钥?我有以下代码:

static int create_signature(unsigned char* hash)
{
  EC_KEY *eckey=NULL;
  EC_GROUP *ecgroup=NULL;
  EVP_PKEY *evpkey=NULL;
  unsigned char *signature=NULL;
  point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
  int signature_size, block_size;
  unsigned char * block=NULL;

  ecgroup = get_ec_group_192();
  EC_GROUP_set_asn1_flag(ecgroup, OPENSSL_EC_NAMED_CURVE);
  EC_GROUP_set_point_conversion_form(ecgroup, form);
  eckey=EC_KEY_new();
  EC_KEY_set_group(eckey,ecgroup);
  EC_KEY_generate_key(eckey);
  evpkey=EVP_PKEY_new();
  EVP_PKEY_assign_EC_KEY(evpkey,eckey);
  signature=OPENSSL_malloc(EVP_PKEY_size(evpkey));

  ECDSA_sign(0, hash, sizeof(hash), signature, &signature_size, eckey);

  printf("%s", signature);
  return 0;
}

The function get_ec_group_192()is created by running openssl ecparam -C -name secp192k1 -genkeywhich also generates some EC PARAMETERSand a EC PRIVATE KEY.

该函数get_ec_group_192()是通过运行创建的,openssl ecparam -C -name secp192k1 -genkey它还会生成 someEC PARAMETERS和 a EC PRIVATE KEY

What I am trying to do is to encrypt the message contained in hashwith my private key so that only public key can decrypt it. Is that possible with the above code, or am I doing this completely wrong?

我想要做的是hash用我的私钥加密包含在其中的消息,以便只有公钥才能解密它。上面的代码可以做到这一点,还是我这样做完全错误?

回答by this.josh

The following verifies successfully for me:

以下为我成功验证:

//compiled with gcc -g -lssl -UOPENSSL_NO_EC SO2228860.c -lcrypto
#include <openssl/ec.h>      // for EC_GROUP_new_by_curve_name, EC_GROUP_free, EC_KEY_new, EC_KEY_set_group, EC_KEY_generate_key, EC_KEY_free
#include <openssl/ecdsa.h>   // for ECDSA_do_sign, ECDSA_do_verify
#include <openssl/obj_mac.h> // for NID_secp192k1


static int create_signature(unsigned char* hash)
{
    int function_status = -1;
    EC_KEY *eckey=EC_KEY_new();
    if (NULL == eckey)
    {
        printf("Failed to create new EC Key\n");
        function_status = -1;
    }
    else
    {
        EC_GROUP *ecgroup= EC_GROUP_new_by_curve_name(NID_secp192k1);
        if (NULL == ecgroup)
        {
            printf("Failed to create new EC Group\n");
            function_status = -1;
        }
        else
        {
            int set_group_status = EC_KEY_set_group(eckey,ecgroup);
            const int set_group_success = 1;
            if (set_group_success != set_group_status)
            {
                printf("Failed to set group for EC Key\n");
                function_status = -1;
            }
            else
            {
                const int gen_success = 1;
                int gen_status = EC_KEY_generate_key(eckey);
                if (gen_success != gen_status)
                {
                    printf("Failed to generate EC Key\n");
                    function_status = -1;
                }
                else
                {
                    ECDSA_SIG *signature = ECDSA_do_sign(hash, strlen(hash), eckey);
                    if (NULL == signature)
                    {
                        printf("Failed to generate EC Signature\n");
                        function_status = -1;
                    }
                    else
                    {

                        int verify_status = ECDSA_do_verify(hash, strlen(hash), signature, eckey);
                        const int verify_success = 1;
                        if (verify_success != verify_status)
                        {
                            printf("Failed to verify EC Signature\n");
                            function_status = -1;
                        }
                        else
                        {
                            printf("Verifed EC Signature\n");
                            function_status = 1;
                        }
                    }
                }
            }
            EC_GROUP_free(ecgroup);
        }
        EC_KEY_free(eckey);
    }

  return function_status;
}

int main( int argc , char * argv[] )
{
    unsigned char hash[] = "c7fbca202a95a570285e3d700eb04ca2";
    int status = create_signature(hash);
    return(0) ;
}

回答by donald schleede

Their is a small bug in the above code. The hash that is passed is an unsigned char, this hash CAN have 0x00 values in it! Do NOT use the strlen(hash) to calculate the length, as that will possibly pass the incorrect length to the routine IF the hash has a 0x00 in it anywhere. Hashes are fixed length, and should be passed as such. sha256 for example should be of length 64.

他们是上面代码中的一个小错误。传递的散列是一个无符号字符,这个散列可以有 0x00 个值!不要使用 strlen(hash) 来计算长度,因为如果哈希在任何地方都有 0x00,这可能会将不正确的长度传递给例程。哈希是固定长度的,应该这样传递。例如 sha256 的长度应该是 64。