WIN32 上的 JWT 验证
JWT Verification on WIN32
我正在尝试使用 WIN32 加密函数验证 RS512 JWT。我有 public 密钥、要验证的数据和作为内存数组的签名数据。我能够创建证书上下文并导入 public 密钥,但到目前为止我还无法验证签名。无论我尝试什么,我都会得到 STATUS_INVALID_PARAMETER 结果。
我看过几篇关于必须反转部分或全部数据的帖子:
- 反转 public 键会阻止它加载。
- 反转 dataBuffer 和 signatureBuffer 的 either/both 仍然导致 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 );
}
我错过了文档中说明数据需要散列的部分。在对数据 (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 );
}
我正在尝试使用 WIN32 加密函数验证 RS512 JWT。我有 public 密钥、要验证的数据和作为内存数组的签名数据。我能够创建证书上下文并导入 public 密钥,但到目前为止我还无法验证签名。无论我尝试什么,我都会得到 STATUS_INVALID_PARAMETER 结果。
我看过几篇关于必须反转部分或全部数据的帖子:
- 反转 public 键会阻止它加载。
- 反转 dataBuffer 和 signatureBuffer 的 either/both 仍然导致 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 );
}
我错过了文档中说明数据需要散列的部分。在对数据 (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 );
}