C++ OpenSSL在EVP_VerifyFinal上失败

C++ OpenSSL在EVP_VerifyFinal上失败,c++,encryption,openssl,rsa,C++,Encryption,Openssl,Rsa,在浏览了几天互联网和openssl文档之后,我遇到了麻烦。我正在尝试使用私钥对消息进行签名,然后使用公钥验证消息的真实性 密钥生成代码: //Generate RSA Keys EVP_PKEY_CTX* KeyCtx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); if (KeyCtx == nullptr) return false; if (EVP_PKEY_keygen_init(KeyCtx) &l

在浏览了几天互联网和openssl文档之后,我遇到了麻烦。我正在尝试使用私钥对消息进行签名,然后使用公钥验证消息的真实性

密钥生成代码:

    //Generate RSA Keys
    EVP_PKEY_CTX* KeyCtx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
    if (KeyCtx == nullptr)
        return false;

    if (EVP_PKEY_keygen_init(KeyCtx) <= 0)
        return false;

    if (EVP_PKEY_CTX_set_rsa_keygen_bits(KeyCtx, RSA_KeyLen) <= 0)
        return false;

    if (EVP_PKEY_keygen(KeyCtx, &m_ServerKeyPair) <= 0)
        return false;

    if (EVP_PKEY_keygen(KeyCtx, &m_ClientKeyPair) <= 0)
        return false;

    //Write Keys to EVP_PKEYS for actual internal encryption,BIO mem is wiped after read so we need a new copy
    PEM_read_bio_PrivateKey(KeyToPrivBio(m_ServerKeyPair), &m_ServerPrivateKey, NULL, NULL);
    PEM_read_bio_PUBKEY(KeyToPubBio(m_ServerKeyPair), &m_ServerPublicKey, NULL, NULL);
    PEM_read_bio_PrivateKey(KeyToPrivBio(m_ClientKeyPair), &m_ClientPrivateKey, NULL, NULL);
    PEM_read_bio_PUBKEY(KeyToPubBio(m_ClientKeyPair), &m_ClientPublicKey, NULL, NULL);

这显然是没有帮助的,请有人指出我可能做错了什么。这是我第一次深入到openssl,所以这里可能会有一些大问题。

多亏了JWW和indiv,我才能够解决我的问题,这是我使用旧API和不正确的返回检查的问题。解决方案:

bool SecureCrypto::RSASign(const unsigned char* Msg, size_t MsgLen,unsigned char** EncMsg, size_t* MsgLenEnc)
{
    if (EVP_DigestSignInit(m_RSASignCtx,NULL, EVP_sha256(), NULL,m_ServerPrivateKey) <= 0)
    {
        printf("Failed Init\n");
        return false;
    }

    if (EVP_DigestSignUpdate(m_RSASignCtx, Msg, MsgLen) <= 0)
    {
        printf("Failed Update\n");
        return false;
    }

    //Get Hash Size
    if (EVP_DigestSignFinal(m_RSASignCtx, NULL,MsgLenEnc) <=0)
    {
        printf("Failed Final Sign\n");
        return false;
    }

    //Allocate Space for hash
    *EncMsg = (unsigned char*)malloc(*MsgLenEnc);
    if (EVP_DigestSignFinal(m_RSASignCtx, *EncMsg, MsgLenEnc) <= 0)
    {
        printf("Failed Final Sign 1\n");
        return false;
    }

    EVP_MD_CTX_cleanup(m_RSASignCtx);

    return true;
}

bool SecureCrypto::RSAVerifySignature(const unsigned char* MsgHash, size_t MsgHashLen,unsigned char* Msg, size_t MsgLen,bool* Authentic)
{
    if (EVP_DigestVerifyInit(m_RSAVerifyCtx,NULL, EVP_sha256(),NULL,m_ServerPrivateKey) <= 0)
    {
        printf("Failed Verify Init\n");
        return false;
    }

    if (EVP_DigestVerifyUpdate(m_RSAVerifyCtx, Msg, MsgLen) <= 0)
    {
        printf("Failed Verify \n");
        return false;
    }

    int AuthStatus = EVP_DigestVerifyFinal(m_RSAVerifyCtx, (unsigned char*)MsgHash, MsgHashLen);

    if (AuthStatus==1)
    {
        //Message Authentic
        *Authentic = true;
        EVP_MD_CTX_cleanup(m_RSAVerifyCtx);
        return true;
    } else if(AuthStatus==0){
        //Message Not Authentic
        *Authentic = false;
        EVP_MD_CTX_cleanup(m_RSAVerifyCtx);
        return true; //Still did our job correctly
    } else{
        printf("Error\n");
        *Authentic = false;
        EVP_MD_CTX_cleanup(m_RSAVerifyCtx);
        return false;
    }
}
bool SecureCrypto::RSASign(常量unsigned char*Msg,size\t MsgLen,unsigned char**EncMsg,size\t*MsgLenEnc)
{

if(EVP_DigestSignInit(m_RSASignCtx,NULL,EVP_sha256(),NULL,m_ServerPrivateKey)if
EVP_VerifyFinal()
返回0,那么这意味着签名验证失败,并且不会设置错误代码,因为这是函数的正常操作。您应该分别处理小于0和等于0的情况。好的,我将对此进行更改,但这里的大问题是为什么它的失败
EVP\u Sign
EVP\u Verify
被取消预设的,不应该使用。现在就应该使用
EVP\u DigestSign
。“在浏览互联网和openssl文档几天后…”-您还应该访问。这是一个正式的OpenSSL示例。它应该与复制/粘贴一起使用。或者访问
/apps
中的一个示例应用程序。在wiki示例之前,我们必须对应用程序目录进行grep。在本例中,您在rsavirifysignature中使用
m_ServerPrivateKey
。rsavirifysignature中的rsaviration验证点不就是您可以用消息、散列和公钥验证签名?为什么在此处使用私钥?这是我测试到此站点的复制和粘贴失败。你完全正确,它应该使用服务器公钥。我的最终openssl包装可以在此处查看:
bool SecureCrypto::RSAVerifySignature(const unsigned char* MsgHash, size_t MsgHashLen,unsigned char* Msg, size_t MsgLen)
{
    if (EVP_VerifyInit(m_RSAVerifyCtx, EVP_sha1()) <= 0)
    {
        printf("Failed Verify Init\n");
        return false;
    }

    if (EVP_VerifyUpdate(m_RSAVerifyCtx, Msg, MsgLen) <= 0)
    {
        printf("Failed Verify \n");
        return false;
    }

    if (EVP_VerifyFinal(m_RSAVerifyCtx, MsgHash, MsgHashLen, m_ServerPublicKey)<=0);
    {
        printf("Failed Final Verify %s\n",ERR_error_string(ERR_get_error(),NULL));
        return false;
    }
    EVP_MD_CTX_cleanup(m_RSAVerifyCtx);
    return true;
}
error:00000000:lib(0):func(0):reason(0)
bool SecureCrypto::RSASign(const unsigned char* Msg, size_t MsgLen,unsigned char** EncMsg, size_t* MsgLenEnc)
{
    if (EVP_DigestSignInit(m_RSASignCtx,NULL, EVP_sha256(), NULL,m_ServerPrivateKey) <= 0)
    {
        printf("Failed Init\n");
        return false;
    }

    if (EVP_DigestSignUpdate(m_RSASignCtx, Msg, MsgLen) <= 0)
    {
        printf("Failed Update\n");
        return false;
    }

    //Get Hash Size
    if (EVP_DigestSignFinal(m_RSASignCtx, NULL,MsgLenEnc) <=0)
    {
        printf("Failed Final Sign\n");
        return false;
    }

    //Allocate Space for hash
    *EncMsg = (unsigned char*)malloc(*MsgLenEnc);
    if (EVP_DigestSignFinal(m_RSASignCtx, *EncMsg, MsgLenEnc) <= 0)
    {
        printf("Failed Final Sign 1\n");
        return false;
    }

    EVP_MD_CTX_cleanup(m_RSASignCtx);

    return true;
}

bool SecureCrypto::RSAVerifySignature(const unsigned char* MsgHash, size_t MsgHashLen,unsigned char* Msg, size_t MsgLen,bool* Authentic)
{
    if (EVP_DigestVerifyInit(m_RSAVerifyCtx,NULL, EVP_sha256(),NULL,m_ServerPrivateKey) <= 0)
    {
        printf("Failed Verify Init\n");
        return false;
    }

    if (EVP_DigestVerifyUpdate(m_RSAVerifyCtx, Msg, MsgLen) <= 0)
    {
        printf("Failed Verify \n");
        return false;
    }

    int AuthStatus = EVP_DigestVerifyFinal(m_RSAVerifyCtx, (unsigned char*)MsgHash, MsgHashLen);

    if (AuthStatus==1)
    {
        //Message Authentic
        *Authentic = true;
        EVP_MD_CTX_cleanup(m_RSAVerifyCtx);
        return true;
    } else if(AuthStatus==0){
        //Message Not Authentic
        *Authentic = false;
        EVP_MD_CTX_cleanup(m_RSAVerifyCtx);
        return true; //Still did our job correctly
    } else{
        printf("Error\n");
        *Authentic = false;
        EVP_MD_CTX_cleanup(m_RSAVerifyCtx);
        return false;
    }
}