我使用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;
}