1.间接上源码:

#include <stdio.h>#include <string.h>#include <openssl/ecdsa.h>#include <openssl/pem.h>#include <openssl/err.h>// base64 编码char *base64_encode(const char *buffer, int length) {    BIO *bmem = NULL;    BIO *b64 = NULL;    BUF_MEM *bptr;    char *buff = NULL;        b64 = BIO_new(BIO_f_base64());    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);    bmem = BIO_new(BIO_s_mem());    b64 = BIO_push(b64, bmem);    BIO_write(b64, buffer, length);    BIO_flush(b64);    BIO_get_mem_ptr(b64, &bptr);    BIO_set_close(b64, BIO_NOCLOSE);    buff = (char *)malloc(bptr->length + 1);    memcpy(buff, bptr->data, bptr->length);    buff[bptr->length] = 0;    BIO_free_all(b64);    return buff;}// base64 解码char *base64_decode(char *input, int length) {    BIO *b64 = NULL;    BIO *bmem = NULL;    char *buffer = NULL;    buffer = (char *)malloc(length);    memset(buffer, 0, length);    b64 = BIO_new(BIO_f_base64());    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);    bmem = BIO_new_mem_buf(input, length);    bmem = BIO_push(b64, bmem);    BIO_read(bmem, buffer, length);    BIO_free_all(bmem);    return buffer;}//公钥验证签名int my_verify(const char *input, int input_len, ECDSA_SIG *signret, const char *pub_key_fn){    EC_KEY *p_dsa = NULL;    FILE *file = NULL;    int ret = 0;    unsigned char digest[EVP_MAX_MD_SIZE];    unsigned int digest_len = 0;    EVP_MD_CTX md_ctx;    if((file = fopen(pub_key_fn, "rb")) == NULL) {        ret = -1;        return ret;    }    if((p_dsa = PEM_read_EC_PUBKEY(file, NULL,NULL,NULL )) == NULL) { // 获取公钥的ec key        ret = -2;        fclose(file);        return ret;    }    fclose(file);    EVP_MD_CTX_init(&md_ctx);    if (!EVP_DigestInit(&md_ctx, EVP_sha256())) {        printf("EVP_digest fail \n");        return 0;    }    if (!EVP_DigestUpdate(&md_ctx, (const void *)input, input_len)) {        printf("EVP_DigestUpdate fail \n");        return 0;    }    if (!EVP_DigestFinal(&md_ctx, digest, &digest_len)) { // 待签名音讯用sha256生成256比特的签名摘要        printf("EVP_DigestFinal fail \n");                return 0;    }    printf("verify digest: %s\n", digest);    ret = ECDSA_do_verify(digest, digest_len, signret, p_dsa); // 对签名摘要进行验签失去后果    if (ret == -1) {        ret = -3;        printf("ECDSA_verify err!\n");        EC_KEY_free(p_dsa);        return ret;    } else if (ret == 0) {        ret = -3;        printf("ECDSA_verify err incorrect signature!\n");        EC_KEY_free(p_dsa);        return ret;    } else {       printf("ECDSA_verify ok\n");    }    printf("verify is ok!\n");    EC_KEY_free(p_dsa);    return 0;}//私钥签名int my_sign(const char *input, int input_len, const char *pri_key_fn){    EC_KEY *p_dsa = NULL;    ECDSA_SIG *s;    FILE *file = NULL;    unsigned char *data[2];    int nid;    int signlen = 0;    int i = 0;    int ret = 0;    unsigned char digest[EVP_MAX_MD_SIZE];    unsigned int digest_len = 0;    EVP_MD_CTX md_ctx;    memset(data, 0x00, sizeof(data));    nid = 0;    file = fopen(pri_key_fn, "rb");    if(!file)    {        ret = -1;        return ret;    }    if((p_dsa = PEM_read_ECPrivateKey(file, NULL, NULL, NULL)) == NULL) { // 获取私钥的ec key        ret = -2;        fclose(file);        return ret;    }    fclose(file);    EVP_MD_CTX_init(&md_ctx);    if (!EVP_DigestInit(&md_ctx, EVP_sha256())) {        printf("EVP_digest fail \n");        return 0;    }    if (!EVP_DigestUpdate(&md_ctx, (const void *)input, input_len)) {        printf("EVP_DigestUpdate fail \n");        return 0;    }    if (!EVP_DigestFinal(&md_ctx, digest, &digest_len)) { // 待签名音讯用sha256生成256比特的签名摘要        printf("EVP_DigestFinal fail \n");        return 0;    }    printf("sign digest: %s\n", digest);    s = ECDSA_do_sign(digest, digest_len, p_dsa); // 对签名摘要进行签名失去签名数据s    if(s == NULL) {        ret = -3;        EC_KEY_free(p_dsa);        return ret;    }    data[0] = BN_bn2hex(s->r); //二进制转十六进制    data[1] = BN_bn2hex(s->s);    EC_KEY_free(p_dsa);    ECDSA_SIG_free(s);    printf("%s\n", data[0]);    printf("%s\n", data[1]);    free(data[0]);    free(data[1]);    return 0;}int main(int argc, char**argv){    char src[512+1];    char dst_str[2][512+1];    int src_len;    int ret;    FILE *f;    memset(src, 0x00, sizeof(src));    memset(dst_str, 0x00, sizeof(dst_str));    if(argv[1][0] == 's') {        strcpy(src, "hello world"); // 待签名音讯        src_len = strlen(src) ;        ret = my_sign(src, src_len, argv[2]);        if(ret) {                fprintf(stderr, "Error\n");        }    }    else {        ECDSA_SIG *s = (ECDSA_SIG *)malloc(sizeof(ECDSA_SIG));        strcpy(src, "hello world"); // 须要验证的签名音讯        strncpy(dst_str[0], argv[2], 512);        strncpy(dst_str[1], argv[3], 512);        src_len = strlen(src);        s->r = BN_new();        s->s = BN_new();        BN_hex2bn(&(s->r), dst_str[0]); //十六进制转二进制        BN_hex2bn(&(s->s), dst_str[1]);        ret = my_verify(src, src_len, s, argv[1]);        if(ret) {                fprintf(stderr, "Error\n");        }        BN_free(s->r);        BN_free(s->s);        free(s);    }    return 0;}

2.编译环境

openssl版本为1.0.2g,openssl version查看openssl的版本,其余版本自行验证
base的编解码代码也有,这里demo暂不应用

3.编译

gcc ecdsa.c -o ecdsa -lssl -lcrypto

4.生成私钥和公钥

openssl ecparam -genkey -name prime256v1 -out eccpri256.keyopenssl ec -in eccpri256.key -pubout -out eccpri256.pem

5.运行后果

root@ubuntu:/home/workspace/test/demo_sign# ./ecdsa s eccpri256.keysign digest: ¹M'¹M¥.R}«尣zS E948080F0496BEAF2303A184BF9F67491AB95920BD3951DBABA36813768273DF568224ECBA9A83161E1494DAB02884B123A376DE57A9A7BA4F018A5BB9E38404root@ubuntu:/home/workspace/test/demo_sign# ./ecdsa eccpri256.pem E948080F0496BEAF2303A184BF9F67491AB95920BD3951DBABA36813768273DF 568224ECBA9A83161E1494DAB02884B123A376DE57A9A7BA4F018A5BB9E38404verify digest: ¹M'¹M¥.R}«尣zS3*fO@ECDSA_verify okverify is ok!