首页 文章

使用SHA在C中使用RSA对数据进行签名

提问于
浏览
1

我必须使用带有RSA签名的SHA1签署一个数据数组,我的私钥在C中 . 我正在使用OpenSSl库 . 但是我总是没有得到OPENSSL_Applink错误 . 我试过以下:

  • 包括applink.c

  • 静态链接库只有libcrypto-1_1.a

  • 调试applink.c以查看表的问题

  • 因为我没有包含applink.c我在我的项目中手动添加了相同文件名的源代码,这导致了无响应的应用程序 .

我正在使用eclipseCDT氧气版 . 我是openSSl库中的一个初学者,也想知道如果有人知道这样做的好例子就给我发送链接 . 我还尝试添加OpenSSL_add_all_digests()和OpenSSL_add_all_algorithms(),但没有成功 .

注意:这里的代码可能是错误的,但我的问题是当编译器遇到openssl库项目崩溃的第一个自定义函数时错误没有OPENSSL_Applink,所以这是我的主要问题,而不是修复代码本身 .

这是一段代码:

int rsaSign(char *in_file, char * sig_file){

    char *data = NULL;
    int data_len;
    unsigned int sig_len;
    unsigned char *sig;
    int err = -1;

    OpenSSL_add_all_digests();
    FILE *fd;
    EVP_PKEY *priv_key = EVP_PKEY_new();
    RSA *privkey = NULL;
       printf( "we are here..\n");

    if ((fd = fopen(PRIVKEY_FILE, "r")) == NULL){
        printf("error reading file\n");
        exit(0);
    }

    privkey = RSA_new();
    if (!PEM_read_PrivateKey(fd, &privkey, NULL, NULL))
    {
        fprintf(stderr, "Error loading RSA Private Key File.\n");
        return 2;
    }

    fclose(fd);

    if (!EVP_PKEY_assign_RSA (priv_key, privkey))
    {
        fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
        return 3;
    }

    if (!priv_key) {
        printf("no private key\n");
    }
    EVP_PKEY_set1_RSA(privkey, priv_key);


    EVP_MD_CTX *ctx = EVP_MD_CTX_create();

    const EVP_MD *md = EVP_get_digestbyname("SHA1");

    if (!md) {
        fprintf(stderr, "Error creating message digest");
        fprintf(stderr, " object, unknown name?\n");
        ERR_print_errors_fp(stderr);
        exit(1);
    }



    if (!EVP_SignInit(ctx, md))
        {
            fprintf(stderr, "EVP_SignInit: failed.\n");
            EVP_PKEY_free(priv_key);
            return 3;
        }
    printf( "now to sign update..\n");
    data = readFile(in_file);
    data_len = strlen(data);
    printf("data len = %d\n", data_len);

    if (!EVP_SignUpdate(ctx, data, data_len))
    {
        fprintf(stderr, "EVP_SignUpdate: failed.\n");
        EVP_PKEY_free(priv_key);
        return 3;
    }
    printf( "now to sign final..\n");

    sig = malloc(EVP_PKEY_size(privkey)); //!!!!! SEGMENTATION FAULT HERE !!!!!


    if (!EVP_SignFinal(ctx, &sig, &sig_len, priv_key))
    {
        fprintf(stderr, "EVP_SignFinal: failed.\n");
        free(sig);
        EVP_PKEY_free(priv_key);
        return 3;
    }

    free(data);
    free(sig);
    EVP_PKEY_free(priv_key);
    return EXIT_SUCCESS;

    }

1 回答

  • 0

    您的代码将 &privkey RSA** 类型传递给 PEM_read_PrivateKey ,这需要(根据其原型) EVP_PKEY** ;你的编译器应该已经诊断出来了 . 同样 EVP_PKEY_size 要求 EVP_PKEY* 不是 RSA* . 使用泛型读取,您根本不需要任何 RSA* ,也不需要也不能使用 EVP_PKEY_assign_RSA .

    如果您的代码(包括对OpenSSL和 #include "applink.c" 的所有调用)都在EXE中而不在DLL中,那么Applink应该可以工作 - 是吗?

    但是, you can eliminate the need for Applink 甚至通过避免使用 FILE* 并使用 BIO* 表单的API进行动态链接 . 因此,而不是:

    FILE* f = fopen (file,"r");
    if( f==NULL ) ...error... 
    ... PEM_read_PrivateKey (f, &evpkey, NULL, NULL) ...
    fclose(f);
    

    使用:

    BIO* b = BIO_new_file (file,"r");
    if( b==NULL ) ...error...
    ... PEM_read_bio_PrivateKey (b, &evpkey, NULL, NULL) ...
    BIO_close(b);
    

    或者可能但更笨拙:

    FILE* f = fopen (file,"r"); if( f==NULL ) ...error...;
    char* buf = ...read all data from f into allocated memory...;
    int len = ...length of data in buf...;
    fclose (f);
    BIO* b = BIO_new_mem_buf (buf,len);
    ... PEM_read_bio_PrivateKey (b, &evpkey, NULL, NULL) ...
    ... free buf as appropriate ...
    

    PS:我不是't know if the MinGW package has man pages, but most Windows packages (other than Cygwin and now WSL) don' . 如果不是,您应该书签并使用https://www.openssl.org/docs/manpages.html下的相应目录 .

相关问题