RSA Sign:OpenSSL

时间:2011-03-15 15:18:30

标签: c openssl

我正在尝试使用Openssl的EVP接口进行编码,以便使用SHA1进行RSA签名。后来我想用不同的摘要算法和不同的签名算法扩展签名(通用的sor,因此使用EVP)。

每当我尝试检索私钥的大小时,我似乎都会遇到分段错误

有人能告诉我如何纠正这个问题吗?

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;

}

2 个答案:

答案 0 :(得分:7)

我不是那个特定图书馆的专家,但是仔细阅读了API文档后,我想:

EVP_PKEY_set1_RSA(privkey, priv_key);

应该是:

EVP_PKEY_set1_RSA(priv_key, privkey);

同样不应该将您突出显示为SEGFAULTing的行引用priv_key而不是privkey

sig = malloc(EVP_PKEY_size(priv_key));

如果您将变量名更改为更容易区分的内容(而不是privkeypriv_key,请使用priv_key_RSApriv_key_EVP <,这些错误会更容易看到/ p>

只有下划线不同的变量是真的坏主意:)

答案 1 :(得分:7)

你有几个问题:

  • PEM_read_PrivateKey()需要EVP_PKEY **,而不是RSA ** - 事实上,您根本不需要RSA *个对象;
  • 您不应该致电EVP_PKEY_assign_RSA();
  • 您不应该致电EVP_PKEY_set1_RSA()

要加载私钥,您只需执行以下操作:

EVP_PKEY *priv_key = NULL;

if (!PEM_read_PrivateKey(rsa_pkey_file, &priv_key, NULL, NULL))
{
    fprintf(stderr, "Error loading Private Key File.\n");
    return 2;
}

您现在可以致电EVP_PKEY_size(priv_key)来确定密钥大小。

此外,您的EVP_SignFinal()来电错误 - 您应该通过sig,而不是&sig