我想用OpenSSL验证JSON Web Tokens (JWT),但我无法让验证成功。以下是使用Verifying JWT signed with the RS256 algorithm using public key in C#中的令牌和密钥的代码:
QByteArray token = "eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAsCiAiY19oYXNoIjogIkxEa3RLZG9RYWszUGswY25YeENsdEEiCn0.XW6uhdrkBgcGx6zVIrCiROpWURs-4goO1sKA4m9jhJIImiGg5muPUcNegx6sSv43c5DSn37sxCRrDZZm4ZPBKKgtYASMcE20SDgvYJdJS0cyuFw7Ijp_7WnIjcrl6B5cmoM6ylCvsLMwkoQAxVublMwH10oAxjzD6NEFsu9nipkszWhsPePf_rM4eMpkmCbTzume-fzZIi5VjdWGGEmzTg32h3jiex-r5WTHbj-u5HL7u_KP3rmbdYNzlzd1xWRYTUs4E8nOTgzAUwvwXkIQhOh5TPcSMBYy6X3E7-_gr9Ue6n4ND7hTFhtjYs3cjNKIA08qm5cpVYFMFMG6PkhzLQ);
QByteArray rsaModulus = QByteArray::fromBase64("w7Zdfmece8iaB0kiTY8pCtiBtzbptJmP28nSWwtdjRu0f2GFpajvWE4VhfJAjEsOcwYzay7XGN0b-X84BfC8hmCTOj2b2eHT7NsZegFPKRUQzJ9wW8ipn_aDJWMGDuB1XyqT1E7DYqjUCEOD1b4FLpy_xPn6oV_TYOfQ9fZdbE5HGxJUzekuGcOKqOQ8M7wfYHhHHLxGpQVgL0apWuP2gDDOdTtpuld4D2LK1MZK99s9gaSjRHE8JDb1Z4IGhEcEyzkxswVdPndUWzfvWBBWXWxtSUvQGBRkuy1BHOa4sP6FKjWEeeF7gm7UMs2Nm2QUgNZw6xvEDGaLk4KASdIxRQ");
QByteArray rsaExponent = QByteArray::fromBase64("AQAB");
QList<QByteArray> tokenParts = token.split('.');
QByteArray header = tokenParts[0];
QByteArray body = tokenParts[1];
QByteArray sig = tokenParts[2];
QByteArray pad = sig.length() % 4 ? "" : QByteArray("====").left(4 - (sig.length() % 4));
QByteArray decodedSig = QByteArray::fromBase64(sig.replace('_', '/').replace('-', '+') + pad);
BIGNUM *rsaModulusBn = BN_bin2bn((unsigned char *)rsaModulus.data(), rsaModulus.length(), NULL);
BIGNUM *rsaExponentBn = BN_bin2bn((unsigned char *)rsaExponent.data(), rsaExponent.length(), NULL);
RSA *rsa = RSA_new();
if (rsa == NULL) printf("cannot allocate RSA\n");
rsa->n = rsaModulusBn;
rsa->e = rsaExponentBn;
EVP_PKEY *key = EVP_PKEY_new();
if (1 != EVP_PKEY_set1_RSA(key, rsa)) ERR_print_errors_fp(stdout);
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
if (ctx == NULL) printf("cannot allocate MD CTX\n");
if (1 != EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, key)) ERR_print_errors_fp(stdout);
if (1 != EVP_DigestVerifyUpdate(ctx, (unsigned char *)header.data(), header.length())) ERR_print_errors_fp(stdout);
if (1 != EVP_DigestVerifyUpdate(ctx, ".", 1)) ERR_print_errors_fp(stdout);
if (1 != EVP_DigestVerifyUpdate(ctx, (unsigned char *)body.data(), body.length())) ERR_print_errors_fp(stdout);
if (1 != EVP_DigestVerifyFinal(ctx, (unsigned char *)decodedSig.data(), decodedSig.length()))
{
printf("failure\n");
ERR_print_errors_fp(stdout);
}
else
{
printf("success\n");
}
if (ctx) EVP_MD_CTX_destroy(ctx);
if (key) EVP_PKEY_free(key);
if (rsa) RSA_free(rsa);
如果它有用,node jwt-to-pem
表示上面的PEM格式的键是:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAw7Zdfmece8iaB0kiTY8pCtiBtzbptJmP28nSWwtdjRu0f2GFpajv
WE4VhfJAjEsOcwYzay7XGN0b+X84BfC8hmCTOj2b2eHT7NsZegFPKRUQzJ9wW8ip
n/aDJWMGDuB1XyqT1E7DYqjUCEOD1b4FLpy/xPn6oV/TYOfQ9fZdbE5HGxJUzeku
GcOKqOQ8M7wfYHhHHLxGpQVgL0apWuP2gDDOdTtpuld4D2LK1MZK99s9gaSjRHE8
JDb1Z4IGhEcEyzkxswVdPndUWzfvWBBWXWxtSUvQGBRkuy1BHOa4sP6FKjWEeeF7
gm7UMs2Nm2QUgNZw6xvEDGaLk4KASdIxRQIDAQAB
-----END RSA PUBLIC KEY-----
验证失败:
10857314492266413637:error:04091077:rsa routines:INT_RSA_VERIFY:wrong signature length:rsa_sign.c:186:
我非常感谢有经验的人查看我的代码,因为我不知道如何调试它而没有一个可比较的实例。
答案 0 :(得分:1)
事实证明,RSA密钥模数和指数也是base64 URL编码。这是有效的代码,horaay:
QByteArray token = "eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAsCiAiY19oYXNoIjogIkxEa3RLZG9RYWszUGswY25YeENsdEEiCn0.XW6uhdrkBgcGx6zVIrCiROpWURs-4goO1sKA4m9jhJIImiGg5muPUcNegx6sSv43c5DSn37sxCRrDZZm4ZPBKKgtYASMcE20SDgvYJdJS0cyuFw7Ijp_7WnIjcrl6B5cmoM6ylCvsLMwkoQAxVublMwH10oAxjzD6NEFsu9nipkszWhsPePf_rM4eMpkmCbTzume-fzZIi5VjdWGGEmzTg32h3jiex-r5WTHbj-u5HL7u_KP3rmbdYNzlzd1xWRYTUs4E8nOTgzAUwvwXkIQhOh5TPcSMBYy6X3E7-_gr9Ue6n4ND7hTFhtjYs3cjNKIA08qm5cpVYFMFMG6PkhzLQ";
QByteArray rsaModulus = QByteArray::fromBase64("w7Zdfmece8iaB0kiTY8pCtiBtzbptJmP28nSWwtdjRu0f2GFpajvWE4VhfJAjEsOcwYzay7XGN0b-X84BfC8hmCTOj2b2eHT7NsZegFPKRUQzJ9wW8ipn_aDJWMGDuB1XyqT1E7DYqjUCEOD1b4FLpy_xPn6oV_TYOfQ9fZdbE5HGxJUzekuGcOKqOQ8M7wfYHhHHLxGpQVgL0apWuP2gDDOdTtpuld4D2LK1MZK99s9gaSjRHE8JDb1Z4IGhEcEyzkxswVdPndUWzfvWBBWXWxtSUvQGBRkuy1BHOa4sP6FKjWEeeF7gm7UMs2Nm2QUgNZw6xvEDGaLk4KASdIxRQ", QByteArray::Base64UrlEncoding);
QByteArray rsaExponent = QByteArray::fromBase64("AQAB", QByteArray::Base64UrlEncoding);
QList<QByteArray> tokenParts = token.split('.');
QByteArray header = tokenParts[0];
QByteArray body = tokenParts[1];
QByteArray sig = QByteArray::fromBase64(tokenParts[2], QByteArray::Base64UrlEncoding);
BIGNUM *rsaModulusBn = BN_bin2bn((unsigned char *)rsaModulus.data(), rsaModulus.length(), NULL);
BIGNUM *rsaExponentBn = BN_bin2bn((unsigned char *)rsaExponent.data(), rsaExponent.length(), NULL);
RSA *rsa = RSA_new();
if (rsa == NULL) printf("cannot allocate RSA\n");
#if defined(OPENSSL_1_1_0)
if (1 != RSA_set0_key(rsa, rsaModulusBn, rsaExponentBn, NULL); ERR_print_errors_fp(stdout);
#else
rsa->n = rsaModulusBn;
rsa->e = rsaExponentBn;
#endif
EVP_PKEY *key = EVP_PKEY_new();
if (1 != EVP_PKEY_set1_RSA(key, rsa)) ERR_print_errors_fp(stdout);
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
if (ctx == NULL) printf("cannot allocate MD CTX\n");
if (1 != EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, key)) ERR_print_errors_fp(stdout);
if (1 != EVP_DigestVerifyUpdate(ctx, (unsigned char *)header.data(), header.length())) ERR_print_errors_fp(stdout);
if (1 != EVP_DigestVerifyUpdate(ctx, ".", 1)) ERR_print_errors_fp(stdout);
if (1 != EVP_DigestVerifyUpdate(ctx, (unsigned char *)body.data(), body.length())) ERR_print_errors_fp(stdout);
if (1 != EVP_DigestVerifyFinal(ctx, (unsigned char *)sig.data(), sig.length()))
{
printf("failure\n");
ERR_print_errors_fp(stdout);
}
else
{
printf("success\n");
}
if (ctx) EVP_MD_CTX_destroy(ctx);
if (key) EVP_PKEY_free(key);
if (rsa) RSA_free(rsa);