使用openssl验证ECDSA签名时出现问题

时间:2017-11-23 10:27:19

标签: openssl digital-signature

我使用openssl来验证智能卡的ECDSA签名。 但是,我在使用两张卡时遇到了麻烦。 挑战发送到卡,签名然后发回。使用公钥验证签名。

我之前在这里发布了一个question,我在那里询问如何将我从卡中获得的普通签名转换为DER格式。那个问题得到了回答,我得到了它的工作。但签名不会验证所有卡(EVP_DigestVerifyFinal()返回0)。 我确实用不同的系统验证来自卡的签名确实可以用公钥验证。但是,我无法查看该系统的代码。

以下是验证代码,其功能是在底部转换签名。

我不是加密专家。我在这里错过了一个需要进入EVP_DigestVerifyInit()的设置吗?是否始终需要使用EVP_sha1()进行初始化? 谢谢你的回答!

bool doAA(std::vector<unsigned char> oRND, std::vector<unsigned char> oSIG, std::vector<unsigned char> oPKEY)
{
    EVP_PKEY* m_pPubkey;
    BIO* keyBio = BIO_new_mem_buf(&oPKEY[0], (int)oPKEY.size());
    m_pPubkey = d2i_PUBKEY_bio(keyBio, NULL);       
    BIO_free(keyBio);

    if (NULL == m_pPubkey)
    {
        std::cout << "Error Public key is NULL" << std::endl;
        return false;
    }

    // check if ECDSA signature and then verify
    int nRes = 0;
    int type = EVP_PKEY_base_id(m_pPubkey);
    if (type == EVP_PKEY_EC)
    {
        EVP_MD_CTX* ctx = EVP_MD_CTX_create();

        nRes = EVP_DigestVerifyInit(ctx, NULL, EVP_sha1(), NULL, m_pPubkey);
        if (1 != nRes)
        {
            EVP_MD_CTX_cleanup(ctx);
            std::cout << "Error EVP_DigestVerifyInit" << std::endl;
            return false;
        }

        nRes = EVP_DigestVerifyUpdate(ctx, &oRND[0], oRND.size());
        if (1 != nRes)
        {
            EVP_MD_CTX_cleanup(ctx);
            std::cout << "Error EVP_DigestVerifyUpdate" << std::endl;
            return false;
        }

        ConvertPlainToDERSignature(oSIG);

        nRes = EVP_DigestVerifyFinal(ctx, &oSIG[0], oSIG.size());
        EVP_MD_CTX_cleanup(ctx);
        if (nRes < 0)
        {
            std::cout << "Error EVP_DigestVerifyFinal failed" << std::endl;
            return false;
        }
        else if (nRes == 0)
        {
            std::cout << "Error EVP_DigestVerifyFinal: Signature could not be verified" << std::endl;
            return false;
        }
    }
    else
    {
        std::cout << "Not a ECDSA Signature" << std::endl;
        return false;
    }

    return nRes == 1;
}

void ConvertPlainToDERSignature(std::vector<unsigned char>& raSignature)
{
    ECDSA_SIG* ec_sig = ECDSA_SIG_new();
    int nLen = raSignature.size() / 2;
    if (NULL == BN_bin2bn(&raSignature[0], nLen, (ec_sig->r)))
    {
        std::cout << "OpensslError " << std::string(ERR_error_string(ERR_get_error(), NULL)) << std::endl;
    }
    std::cout << "ECDSA Signature R: " << std::string(BN_bn2hex(ec_sig->r)) << std::endl;;

    if (NULL == BN_bin2bn(&raSignature[0] + nLen, nLen, (ec_sig->s)))
    {
        std::cout << "OpensslError " << std::string(ERR_error_string(ERR_get_error(), NULL)) << std::endl;
    }
    std::cout << "ECDSA Signature S: " << std::string(BN_bn2hex(ec_sig->s)) << std::endl;;

    int sig_size = i2d_ECDSA_SIG(ec_sig, NULL);
    unsigned char *sig_bytes = new unsigned char[sig_size];
    unsigned char *p;
    memset(sig_bytes, 6, sig_size);

    p = sig_bytes;
    int new_sig_size = i2d_ECDSA_SIG(ec_sig, &p);

    raSignature.clear();

    raSignature.resize(new_sig_size);

    memcpy(&raSignature[0], sig_bytes, new_sig_size);
    delete[] sig_bytes;
}

0 个答案:

没有答案