如何在EVP_SignFinal生成RSA签名时避免SIGABRT

时间:2016-12-08 11:00:00

标签: c++ openssl rsa digital-signature

我正在尝试使用libopenssl为c ++生成RSA签名: 但是当我运行我的代码时,我得到一个SIGABRT。我对libopenssl内部的东西做了一些深入的调试,看看Segfault的来源。我稍后会谈到这个。

首先,我想说清楚,RSA PrivateKey是从.pem文件成功加载的。所以我很确定这不是问题的起源。

所以我的问题是:如何避免SIGABRT及其原因是什么?

我正在为我的B.Sc做这件事。论文所以我非常感谢你的帮助:)。

签名生成功能:

DocumentSignature* RSASignatureGenerator::generateSignature(ContentHash* ch, CryptographicKey* pK) throw(PDVSException) {
    OpenSSL_add_all_algorithms();
    OpenSSL_add_all_ciphers();
    OpenSSL_add_all_digests();

    if(pK == nullptr)
        throw MissingPrivateKeyException();

    if(pK->getKeyType() != CryptographicKey::KeyType::RSA_PRIVATE || !dynamic_cast<RSAPrivateKey*>(pK))
        throw KeyTypeMissmatchException(pK->getPem()->getPath().string(), "Generate RSA Signature");

    //get msg to encrypt
    const char* msg = ch->getStringHash().c_str();

    //get openssl rsa key
    RSA* rsaPK = dynamic_cast<RSAPrivateKey*>(pK)->createOpenSSLRSAKeyObject();

    //create openssl signing context
    EVP_MD_CTX* rsaSignCtx = EVP_MD_CTX_create();
    EVP_PKEY* priKey  = EVP_PKEY_new();
    EVP_PKEY_assign_RSA(priKey, rsaPK);

    //init ctxt
    if (EVP_SignInit(rsaSignCtx, EVP_sha256()) <=0)
        throw RSASignatureGenerationException();

    //add data to sign
    if (EVP_SignUpdate(rsaSignCtx, msg, std::strlen(msg)) <= 0) {
        throw RSASignatureGenerationException();
    }

    //create result byte signature struct
    DocumentSignature::ByteSignature* byteSig = new DocumentSignature::ByteSignature();
    //set size to max possible
    byteSig->size = EVP_MAX_MD_SIZE;
    //alloc buffer memory
    byteSig->data = (unsigned char*)malloc(byteSig->size);

    //do signing
    if (EVP_SignFinal(rsaSignCtx, byteSig->data, (unsigned int*) &byteSig->size, priKey) <= 0)
        throw RSASignatureGenerationException();


    DocumentSignature* res = new DocumentSignature(ch);
    res->setByteSignature(byteSig);

    EVP_MD_CTX_destroy(rsaSignCtx);
    //TODO open SSL Memory leaks -> where to free open ssl stuff?!

    return res;
}

RSA * rsaPK = dynamic_cast(pK) - &gt; createOpenSSLRSAKeyObject();

virtual RSA* createOpenSSLRSAKeyObject() throw (PDVSException) override {
        RSA* rsa = NULL;
        const char* c_string = _pem->getContent().c_str();
        BIO * keybio = BIO_new_mem_buf((void*)c_string, -1);

        if (keybio==NULL)
            throw OpenSSLRSAPrivateKeyObjectCreationException(_pem->getPath());

        rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);

        if(rsa == nullptr)
            throw OpenSSLRSAPrivateKeyObjectCreationException(_pem->getPath());

        //BIO_free(keybio);

        return rsa;
    }

SigAbrt源于文件openssl / crypto / mem.c

void CRYPTO_free(void *str, const char *file, int line)
{
    if (free_impl != NULL && free_impl != &CRYPTO_free) {
        free_impl(str, file, line);
        return;
    }

#ifndef OPENSSL_NO_CRYPTO_MDEBUG
    if (call_malloc_debug) {
        CRYPTO_mem_debug_free(str, 0, file, line);
        free(str);
        CRYPTO_mem_debug_free(str, 1, file, line);
    } else {
        free(str);
    }
#else
    free(str); // <<<<<<< HERE
#endif
}

stacktrace

stacktrace screenshot from debugger (clion - gdb based)

1 个答案:

答案 0 :(得分:0)

我刚刚发现了Bug(我真的不确定这是否是一个libopenssl错误..)

//set size to max possible
byteSig->size = EVP_MAX_MD_SIZE;
//alloc buffer memory
byteSig->data = (unsigned char*)malloc(byteSig->size);

问题是我将缓冲区大小设置为EVP_MAX_MD_SIZE!

(在我看来)非常奇怪的是,你必须保持大小未初始化! (甚至没有设置为0 - 只是&#34; size_t size;&#34;)。

这里奇怪的是,你也必须像我一样分配内存。我不明白这一点因为然后分配了未定义的内存大小..

真正奇怪的是libopenssl在内部将大小设置为0并分配内存本身..(我通过浏览libopenssl源代码检测到这一点)