在C中使用带有RSA的SHA1签名数据数组 [英] Signing array of data using SHA1 with RSA in C

查看:242
本文介绍了在C中使用带有RSA的SHA1签名数据数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须使用带有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;

    }

解决方案

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

如果您的代码(包括对OpenSSL和#include "applink.c"的所有调用)位于DLL的EXE中,则

Applink 应该正常工作-是吗? >

但是,通过避免使用FILE*BIO*形式的API,即使使用动态链接,您也可以消除对Applink的需求.因此,代替:

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:我不知道MinGW软件包是否有手册页,但是大多数Windows软件包(Cygwin和现在的WSL除外)都没有.如果不是,您应该在 https://www.openssl .org/docs/manpages.html .

I have to sign an array of data using SHA1 with RSA signature, with my private key in C. I am using OpenSSl libraries. However i always get no OPENSSL_Applink error. I have tried following:

  • include applink.c
  • static link libraires only libcrypto-1_1.a
  • debug applink.c to see the problem with the table
  • since i coundn't include applink.c i manually added the source code in the same filename in my project, which resulted in a non-responsive application.

I am using eclipseCDT oxygen version. I am a begginer in openSSl libraries and also would like if someone knows a good example of doing it to send me the link. I also tried adding OpenSSL_add_all_digests(), and OpenSSL_add_all_algorithms(), with no success.

Note: The code here may be wrong, but my problem is when compiler hits first custom function of openssl library project crashes with error no OPENSSL_Applink, so that's my main problem, not fixing the code itself.

Here is a code snippet:

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;

    }

解决方案

Your code passes &privkey which is type RSA** to PEM_read_PrivateKey which requires (per its prototype) EVP_PKEY**; your compiler should have diagnosed this. Similarly EVP_PKEY_size requires EVP_PKEY* not RSA*. With the generic read, you don't need any RSA* at all and need not and must not use EVP_PKEY_assign_RSA.

Applink should work if your code (including all calls to OpenSSL AND the #include "applink.c") is in the EXE not in a DLL -- is it?

However, you can eliminate the need for Applink even with dynamic linking by avoiding APIs that use FILE* and using the BIO* forms. Thus instead of:

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

use:

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

or possible but clunkier:

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: I don't know if the MinGW package has man pages, but most Windows packages (other than Cygwin and now WSL) don't. If not you should probably bookmark and use the appropriate directory(ies) under https://www.openssl.org/docs/manpages.html .

这篇关于在C中使用带有RSA的SHA1签名数据数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆