2
我想驗證一個JSON Web Tokens (JWT)與OpenSSL,但我無法驗證成功。下面是一個使用令牌和密鑰我的代碼Verifying JWT signed with the RS256 algorithm using public key in C#:如何使用OpenSSL驗證JSON Web令牌?
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:
我真的很感謝有經驗的人來看看我的代碼,因爲我不知道如何在沒有工作示例的情況下進行調試來進行比較。
'rsa-> N = rsaModulusBn'和'rsa-> E = rsaExponentBn'會下OpnSSL 1.1.0打破,因爲你不會有機會獲得會員。對於1.1.0,您需要使用['RSA_set0_key'](https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_crt_params.html)。另請參見[錯誤:OpenSSL 1.1.0中的「使用不完整類型'RSA {aka struct rsa_st}」](http://stackoverflow.com/q/40549318)。 – jww
謝謝jww。我在目標平臺的openssl中沒有這個功能。我已將評論添加到代碼庫。 – helpwithhaskell