【问题标题】:JWT Verification on WIN32WIN32上的智威汤逊验证
【发布时间】:2021-05-06 21:32:12
【问题描述】:

我正在尝试使用 WIN32 加密函数验证 RS512 JWT。我有公钥、要验证的数据和签名数据作为内存数组。我能够创建证书上下文并导入公钥,但到目前为止我还无法验证签名。无论我尝试什么,我都会得到一个 STATUS_INVALID_PARAMETER 结果。

我看过几篇关于必须反转部分或全部数据的帖子:

  1. 反转公钥会阻止它加载。
  2. 反转 dataBuffer 和 signatureBuffer 中的一个/两个仍会导致 STATUS_INVALID_PARAMETER。
BCRYPT_ALG_HANDLE cryptAlg = nullptr;
if( BCRYPT_SUCCESS( BCryptOpenAlgorithmProvider( &cryptAlg, BCRYPT_RSA_ALGORITHM, nullptr, 0 ) ) )
{
    auto signingKeyBuffer = signingKey.publicKeyBuffer();
    PCCERT_CONTEXT cryptCert = CertCreateCertificateContext( X509_ASN_ENCODING, signingKeyBuffer.getBuffer(), signingKeyBuffer.getSize() );
    if( cryptCert != nullptr )
    {
        BCRYPT_KEY_HANDLE cryptKey;
        if( BCRYPT_SUCCESS( CryptImportPublicKeyInfoEx2( X509_ASN_ENCODING, &cryptCert->pCertInfo->SubjectPublicKeyInfo, 0, nullptr, &cryptKey ) ) )
        {
            BCRYPT_PKCS1_PADDING_INFO pkcs1Info;
            pkcs1Info.pszAlgId = BCRYPT_SHA512_ALGORITHM;
            auto dataBuffer = data;//.reversed();
            auto signatureBuffer = signature;//.reversed();
            auto status = BCryptVerifySignature( cryptKey, &pkcs1Info, dataBuffer.getBuffer(), dataBuffer.getSize(), signatureBuffer.getBuffer(), signatureBuffer.getSize(), BCRYPT_PAD_PKCS1 );

            //status is always STATUS_INVALID_PARAMETER here...
            
            BCryptDestroyKey( cryptKey );
        }
        CertFreeCertificateContext( cryptCert );
    }
    BCryptCloseAlgorithmProvider( cryptAlg, 0 );
}

【问题讨论】:

  • Reversing .. 这对STATUS_INVALID_PARAMETER 来说毫无意义。这个错误是因为错误的标志BCRYPT_PAD_PKCS1 + pPaddingInfo(比如椭圆曲线DSA,这必须是0)或错误的长度(cbSignature)。如果签名错误 - 将是另一个错误 - STATUS_INVALID_SIGNATURE
  • 感谢您的评论,您让我再次阅读文档。我错过了需要散列数据的部分。完成此操作后,一切都按预期进行。
  • 是的,数据当然必须经过哈希处理并从哈希中计算签名。但是,这在您的代码中不可见。也不清楚你得到了什么 cryptAlg - 你没有在代码中使用它
  • 你说得对,我不需要cryptAlg。

标签: c++ winapi jwt wincrypt


【解决方案1】:

我错过了文档中说数据需要散列的部分。在对数据(SHA512)应用相同的哈希后,我能够验证签名。这是工作代码减去错误检查:

//Hash data here.
auto hashedData = data.hash( HashType::SHA512 );

auto signingKeyBuffer = signingKey.publicKeyBuffer();
PCCERT_CONTEXT cryptCert = CertCreateCertificateContext( X509_ASN_ENCODING, signingKeyBuffer.getBuffer(), signingKeyBuffer.getSize() );
if( cryptCert != nullptr )
{
    BCRYPT_KEY_HANDLE cryptKey;
    if( BCRYPT_SUCCESS( CryptImportPublicKeyInfoEx2( X509_ASN_ENCODING, &cryptCert->pCertInfo->SubjectPublicKeyInfo, 0, nullptr, &cryptKey ) ) )
    {
        BCRYPT_PKCS1_PADDING_INFO pkcs1Info;
        pkcs1Info.pszAlgId = cNEHash::algorithmIdForHashType( cAlgorithmType::hashType( algorithm ) );
        auto status = BCryptVerifySignature( cryptKey, &pkcs1Info, hashedData.getBuffer(), hashedData.getSize(), signature.getBuffer(), signature.getSize(), BCRYPT_PAD_PKCS1 );
        if( BCRYPT_SUCCESS( status ) )
            verified = true;
        BCryptDestroyKey( cryptKey );
    }
    CertFreeCertificateContext( cryptCert );
}

【讨论】:

    猜你喜欢
    • 2016-09-21
    • 1970-01-01
    • 2018-07-14
    • 2021-07-15
    • 2017-01-30
    • 2020-12-27
    • 2015-05-25
    • 2015-04-03
    • 2023-03-10
    相关资源
    最近更新 更多