Comments (81)
There is no size limit. I’d need to see an example of the JWT causing the problem. Along with the key.
from libjwt.
I have debugged the issue. The issue is because of algorithm type in the header. I am using PS384 which is not supported in this source.
jwt.c
jwt_alg_t jwt_str_alg(const char *alg)
{
if (alg == NULL)
return JWT_ALG_INVAL;
if (!strcmp(alg, "none"))
return JWT_ALG_NONE;
else if (!strcmp(alg, "HS256"))
return JWT_ALG_HS256;
else if (!strcmp(alg, "HS384"))
return JWT_ALG_HS384;
else if (!strcmp(alg, "HS512"))
return JWT_ALG_HS512;
else if (!strcmp(alg, "RS256"))
return JWT_ALG_RS256;
else if (!strcmp(alg, "RS384"))
return JWT_ALG_RS384;
else if (!strcmp(alg, "RS512"))
return JWT_ALG_RS512;
else if (!strcmp(alg, "ES256"))
return JWT_ALG_ES256;
else if (!strcmp(alg, "ES384"))
return JWT_ALG_ES384;
else if (!strcmp(alg, "ES512"))
return JWT_ALG_ES512;
return JWT_ALG_INVAL;
}
any solutions for this? or will it be supported?
from libjwt.
At the moment, no, it's not supported. You'd either need to use a different algorithm, or look at helping to implement those algorithms in the source code.
from libjwt.
I found this library https://github.com/xmidt-org/cjwt
and it has some samples also. here is a sample for RS256 algorithm,
https://github.com/xmidt-org/cjwt/blob/main/examples/basic/rs_example.c
it works fine as it is. and it is mentioned that PS is also similar to RS. So I tried my JWT token by replacing in the input. but hitting into below error from function EVP_DigestVerifyFinal(md_ctx, in->sig.data, in->sig.len) in jws_evp_openssl.c
Error code : 67625094 Error str : error:0407E086:rsa routines:RSA_verify_PKCS1_PSS_mgf1:last octet invalid
I hope you can help me on this. If we can fix this, we can add this source also to your repository.
update me your thoughts.
from libjwt.
The fix will need to be done in the openssl and gnutls code in LibJWT. Looks like cjwt only changes the expected padding. I think I can use that to change up LibJWT to support the PS algos. I'm out of town for work right now. I might be able to get into this over the weekend.
from libjwt.
@benmcollins any further update?
from libjwt.
Not yet. It was a busy weekend and now the work week has started. I'll try to find some free time.
from libjwt.
Sure
from libjwt.
I just pushed some initial code for OpenSSL. It's untested, but should work. I still need to write some test cases and add GnuTLS support before I can release it.
from libjwt.
I tried with your initial changes. I have given my JWT token and its key from JWKS as input. Now also getting error code 22. I debugged this and came to know that, in file jwt-openssl.c,
pkey = PEM_read_bio_PUBKEY(bufkey, NULL, NULL, NULL);
if (pkey == NULL)
VERIFY_ERROR(EINVAL);
this function unable to read the public key it seems. I have tried two other function as the key type is RSA public key,
- PEM_read_bio_RSA_PUBKEY
- PEM_read_bio_RSAPublicKey
These also return same error.
from libjwt.
Your key needs to be in PEM format.
from libjwt.
What do you mean by key here?
ret = jwt_decode(&jwt, jwt_token, keyid, strlen(keyid));
This highlighted key id ? or the public key which will be generated inside jwt_decode? if you talk about public key, then that is not being given as input to this jwt_decode function. Isn't it?
I think that is the one pkey = PEM_read_bio_PUBKEY(bufkey, NULL, NULL, NULL); function tries to load.
from libjwt.
jwt_decode()
does not generate a public key. It converts a public key in PEM format (passed as the third value) to an internal resource used by OpenSSL.
from libjwt.
This is an example of a 2048 bit RSA Public Key in PEM format:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwtpMAM4l1H995oqlqdMh
uqNuffp4+4aUCwuFE9B5s9MJr63gyf8jW0oDr7Mb1Xb8y9iGkWfhouZqNJbMFry+
iBs+z2TtJF06vbHQZzajDsdux3XVfXv9v6dDIImyU24MsGNkpNt0GISaaiqv51NM
ZQX0miOXXWdkQvWTZFXhmsFCmJLE67oQFSar4hzfAaCulaMD+b3Mcsjlh0yvSq7g
6swiIasEU3qNLKaJAZEzfywroVYr3BwM1IiVbQeKgIkyPS/85M4Y6Ss/T+OWi1Oe
K49NdYBvFP+hNVEoeZzJz5K/nd6C35IX0t2bN5CVXchUFmaUMYk2iPdhXdsC720t
BwIDAQAB
-----END PUBLIC KEY-----
from libjwt.
Oh Sorry. I got it. In token header, actually a key id would be there. I have provided that key as input by mistake.
from libjwt.
Now able to load the public key successfully. But getting error in EVP_DigestVerifyFinal() function. I tried printing the error code as well as the error string.
/* Now check the sig for validity. */
if (EVP_DigestVerifyFinal(mdctx, sig, slen) != 1){
char *buf = NULL, *str = NULL;
unsigned long errcode = ERR_get_error();
printf("Error code : %lu\n", errcode) ;
str = ERR_error_string(errcode, buf);
printf("Error str : %s\n", str);
printf("Error buf : %s\n", buf);
VERIFY_ERROR(EINVAL);
}
Error code : 101224597
Error str : error:06089095:digital envelope routines:EVP_PKEY_CTX_ctrl:no operation set
from libjwt.
Would you be able to provide the code, JWT, and key you are using so I can replicate this locally?
from libjwt.
Sorry to say this. I can't expose my token here. I can provide my public key. Will that be ok?
from libjwt.
I feel like the issue is related to the contexts that you create.
mdctx = EVP_MD_CTX_create();
if (mdctx == NULL)
VERIFY_ERROR(ENOMEM);
pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (pkey_ctx == NULL)
VERIFY_ERROR(ENOMEM);
and their usage. Am not sure. Just suspecting it.
from libjwt.
Can you generate an simple token without any sensitive information and provide the public key for it?
from libjwt.
Token:
eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.G59Ud9dMn2vBP9FCXfSbzpvYcydgTzfXioBR0BTaJTPuNaaYX-EKf-DRnKNSRb5uK553olsmEZ66 t9C0RXT5jsMqlhqSLOJFvtSNeV5uALRmgSIdIx6ApI2Q8LppDYEbzHGEAjkotf9L28SJU43B0wjE PMfWBOZdQE6lEFX9jBPuI7o6va4Vo1Xt9thBIbAkRhq44pEqJ9ziySR0aW_jdBE1tC_05sfsYCIz DAnV2CbonYzFKHB0AHnNHGchazSsjmRjZ3-kelIOMY31ndJTqRtNWivjY-txThZkxTg0BnC_ekOi Frep2Bb3eTfHumxZIMZ8hzIWec7safFCP0ppFg
Public key:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtP2IRnsaYbxOylgebl0O
FitQz78d7L2Ni8XJ4Nz9t4wjJ4Ved5FS05QrGdqPtj1uVs3bQTVahs4OV5wmsfid
D50YzPBqSNvIOM+FcC0wWOqf3ssNCto8WWRM4G8OONoDWiq5wmEFasjODv20jplC
dwrCbKTa9RrrGpbgP68KaQGb/E2HlyCuKIZIVWnV9Z1HKOdStk7uGVqeBmGpdI+O
ebP4/m/qOf1MJicKh+Czr+evqq3ww/NM6hEudMqFTtAa+DXuc5eVc4Kc3wihF3Vm
it9jRbIKogr6JPWznom4g4cNxnIERigquwJoHgR3paEyP/mrESAkyUVva76F2Mhe
SQIDAQAB
-----END PUBLIC KEY-----
You can try this. and below are the commands that I used to generate the above.
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private_key.pem -out public_key.pem
HEADER='{"alg":"PS384","typ":"JWT"}'
PAYLOAD='{"sub":"1234567890","name":"John Doe","iat":1516239022}'
BASE64_HEADER=$(echo -n $HEADER | base64 | tr -d '=' | tr '/+' '-')
BASE64_PAYLOAD=$(echo -n $PAYLOAD | base64 | tr -d '=' | tr '/+' '-')
SIGNATURE=$(echo -n "$BASE64_HEADER.$BASE64_PAYLOAD" | openssl dgst -sha384 -sign private_key.pem | base64 | tr -d '=' | tr '/+' '_-')
JWT_TOKEN="$BASE64_HEADER.$BASE64_PAYLOAD.$SIGNATURE"
just do echo $JWT_TOKEN to get the token.
I tried verifying this signature in jwt.io website. But couldn't.
from libjwt.
I have cloned your source locally and added to my sample app. Below is the sample app code.
#include <stdio.h>
#include <stdlib.h>
#include "jwt.h"
#include <string.h>
int main()
{
jwt_t *jwt = NULL;
const char *name=NULL;
int ret = 0, key_id = 0;
const char* jwt_token = "eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.G59Ud9dMn2vBP9FCXfSbzpvYcydgTzfXioBR0BTaJTPuNaaYX-EKf-DRnKNSRb5uK553olsmEZ66 t9C0RXT5jsMqlhqSLOJFvtSNeV5uALRmgSIdIx6ApI2Q8LppDYEbzHGEAjkotf9L28SJU43B0wjE PMfWBOZdQE6lEFX9jBPuI7o6va4Vo1Xt9thBIbAkRhq44pEqJ9ziySR0aW_jdBE1tC_05sfsYCIz DAnV2CbonYzFKHB0AHnNHGchazSsjmRjZ3-kelIOMY31ndJTqRtNWivjY-txThZkxTg0BnC_ekOi Frep2Bb3eTfHumxZIMZ8hzIWec7safFCP0ppFg";
const char* keyid =
"-----BEGIN PUBLIC KEY-----\n"
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtP2IRnsaYbxOylgebl0O\n"
"FitQz78d7L2Ni8XJ4Nz9t4wjJ4Ved5FS05QrGdqPtj1uVs3bQTVahs4OV5wmsfid\n"
"D50YzPBqSNvIOM+FcC0wWOqf3ssNCto8WWRM4G8OONoDWiq5wmEFasjODv20jplC\n"
"dwrCbKTa9RrrGpbgP68KaQGb/E2HlyCuKIZIVWnV9Z1HKOdStk7uGVqeBmGpdI+O\n"
"ebP4/m/qOf1MJicKh+Czr+evqq3ww/NM6hEudMqFTtAa+DXuc5eVc4Kc3wihF3Vm\n"
"it9jRbIKogr6JPWznom4g4cNxnIERigquwJoHgR3paEyP/mrESAkyUVva76F2Mhe\n"
"SQIDAQAB\n"
"-----END PUBLIC KEY-----";
ret = jwt_decode(&jwt, jwt_token, keyid, strlen(keyid));
printf("ret : %d\n", ret);
if (ret != 0 || jwt == NULL)
{
return 1;
}
name = jwt_get_grant(jwt, "name");
if(name == NULL)
{
printf("\nName is null\n");
return 1;
}
printf("Name : %s\n", name);
return 0;
}
from libjwt.
one more question which could not directly be related this one. Do you know about JWKS ? how can we generate RSA public key from exponent (e) and modulus (n) fields of JWKS json. basically I have to generate the public key in this way in my case. If you have any idea, please share.
from libjwt.
I have fixed the issue now. Now all the verification related openssl functions are passing. But I have few question with you to clarify.
-
In jwt-openssl.c file, specifically in jwt_verify_sha_pem( ) in function, there is a switch case which checks for the Algorithm type. But at the end of the case, you are trying to read the Public key by using PEM_read_bio_PUBKEY( ) which returns EVP_PKEY*. Is this implementation correct ? If the key of RSA type coming as input, will this function work properly ? there you suppose to use either,
PEM_read_bio_RSA_PUBKEY( ) or
PEM_read_bio_RSAPublicKey( ) -
After this key read, you are trying checking for Key type by using EVP_PKEY_id ( ) which accepts only EVP_PKEY* type as input parameter. So obviously when an RSA key comes in, this will not work anymore.
As of now, I have modified your source as per RSA key. I seperated both RSA and ECC based on padding variable. I give you the code as well. Please have a look and provide your final release.
from libjwt.
Please find this Pull request. Review the changes as soon as possible.
from libjwt.
Any further updates? @benmcollins
from libjwt.
Not at the moment. Work has ramped up a little. I’ll find some time to review this week. On why used certain functions, those were in the OpenSSL examples I found and they obviously worked for normal RSA as can be proven through the test cases.
I’ll see what the changes incorporate and make sure it still works with OpenSSL v1.1 as many people still need that compatibility. I may also need to ifdef some of the code for GnuTLS until that code catches up.
from libjwt.
Have been waiting for your update. @benmcollins
from libjwt.
I apologize. Full time job has taken precedent this past week. I skimmed over your code. It looks good but I need to do some cleanup. I think I’ll have time to integrate it on Sunday.
from libjwt.
Is that done @benmcollins ?
from libjwt.
Not yet. I hope to get to it soon.
from libjwt.
hi @benmcollins, please try to get this done by weekend if possible. We have been waiting for this for long time.
from libjwt.
As I'm sure you're aware, I do this project is in my spare time. I have a full-time job and a family. I'll get to it when I have the time. It could be Sunday evening if everything plays out well.
from libjwt.
I'm working on this now.
from libjwt.
really sorry for pushing you. I am not aware of this.
from libjwt.
I made some changes to the head branch. I noticed they we really weren't using pkey_ctx in association with the original pkey, and the padding wasn't being set for PSS. Can you try the head branch with your token?
I'm not dismissing your code, just wanted to fix mine before merging things.
Also, yes, a test case would help this a lot. Thanks.
from libjwt.
I have verified with your latest changes. There is an error in the code, in jwt-openssl.c, in jwt_verify_sha_pem ( ) function, the below line,
if (padding > 0 && (0 < EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding)))
should be,
if (padding < 0 || (0 > EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding)))
I corrected this line by referring my PR (#177). Now the code works fine for my token.
from libjwt.
Ok, I left the padding > 0
because that's what I actually want. We don't want to run the command if padding hasn't been set. I did reverse the comparison in the second part, though.
A test case would really make this easier to validate on my end.
from libjwt.
Ok, I've added a test case. The generated token validates on JWT.io
You may have an issue. Considering your key worked as the code was, it means you are using a regular RSA key. You need to generate an rsa-pss key.
I did it with the following OpenSSL commands:
openssl genpkey -algorithm rsa-pss -pkeyopt rsa_keygen_bits:2048 -out rsa-pss_key_2048.pem
openssl rsa -in rsa-pss_key_2048.pem -pubout -out rsa-pss_key_2048-pub.pem
from libjwt.
I've tested this and got it working with GnuTLS now.
from libjwt.
Ok I will verify from my end. Have you released your source? If I just do, apt install libjwt-dev, will that be fine enough?
from libjwt.
Ok, I've added a test case. The generated token validates on JWT.io
You may have an issue. Considering your key worked as the code was, it means you are using a regular RSA key. You need to generate an rsa-pss key.
I did it with the following OpenSSL commands:
openssl genpkey -algorithm rsa-pss -pkeyopt rsa_keygen_bits:2048 -out rsa-pss_key_2048.pem openssl rsa -in rsa-pss_key_2048.pem -pubout -out rsa-pss_key_2048-pub.pem
and yes. My token is failing for my public key. Is there any specific reason for this change you made? If possible, please let the code as it was earlier.
from libjwt.
I want to make sure it works for someone besides me first. You’ll have to build from the head branch of the repo.
from libjwt.
And the code as it is is correct. Your usage of a normal RSA key is incorrect. It would likely even fail on JWT.io. You need to use the correct RSA-PSS key type.
from libjwt.
I've expanded the test cases for code coverage, and tested this through valgrind on OpenSSL 1.1/3.1 as well as GnuTLS 3.8, on both macOS and Linux (Ubuntu 18.04/x64). Everything is passing.
I'll do a release soon.
from libjwt.
And the code as it is is correct. Your usage of a normal RSA key is incorrect. It would likely even fail on JWT.io. You need to use the correct RSA-PSS key type.
I have taken below token and its public key from your tests,
token:
static const char jwt_ps384_2048[] = "eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9.ey"
"JpYXQiOjE0NzU5ODA1NDUsImlzcyI6ImZpbGVzLm1hY2xhcmEtbGxjLmNvbSIsInJlZi"
"I6IlhYWFgtWVlZWS1aWlpaLUFBQUEtQ0NDQyIsInN1YiI6InVzZXIwIn0.HGI3jmvkMT"
"aot4JM3ElUuEp_ufbG2os116tJdiJsZDM310N3q46vTMAax2QBI3qENEJU_p6qd30i-l"
"f8imM1-D-PiPjMHxvkN5sOkt35MqEwT8I2Xo3ikn8TSBJKPLM4uBBgO49wG2_0tYTfp0"
"GPCinBpkSxttH7T3PmK0gqRXde-5TI99XxUbCAtpS9tSAG4RCpQW4XuhA_Hn4WM8pbGZ"
"vrCvSXWg0ms8fibdDzehuL5AGwJdrabGsPJFU7F2ItrfCaQcVsT6aTSLfFPCv91RK1tl"
"PlUkpxVg6UdVNwzG44o6UgnCil1jLXbcJmIozsJ_tMQHMg2R6YCslah1MrNA";
from libjwt/tests/jwt_rsa_pss.c
and public key from /libjwt/tests/keys/rsa-pss_key_2048-pub.pem
This is not actually working in jwt.io and throws invalid signature.
and one more point is, my token along with its public key is getting verified in jwt.io
Can you share a token and its public key here which verifies in jwt.io as well as in your code.
from libjwt.
The PS384 and PS512 do not, correct. I need to fix that.
However, the PS256 token does in fact verify on JWT.io
from libjwt.
Oh..! but that is also invalid signature it shows for me. (PS256 it is)
from libjwt.
up to Fix logic when check return value of rsa_set_padding this commit. My token works fine which is PS384.
from libjwt.
Ok, I've found the current code base works when compiled with GnuTLS instead of OpenSSL.
Until I figure out why the OpenSSL doesn't work, you can compile against GnuTLS.
from libjwt.
I get the feeling that when I correctly set the key type to RSA-PSS, we no longer need to set the padding. Let me test that.
from libjwt.
up to Fix logic when check return value of rsa_set_padding this commit. My token works fine which is PS384.
Yes, this works for you because you're still using the wrong RSA key type. Fix your key. Generate an rsa-pss key and use that. Please stop using an incorrect key type to test the code. It won't provide us anything useful.
from libjwt.
At this point, please recompile your LibJWT against GnuTLS. Instructions are in the README.md. Also, please regenerate your key so that it is an rsa-pss key.
If you don't want to do that, then you must change libjwt/jwt-gnutls.c
so it uses the RSA
and not RSA_PSS
alg types. This would be invalid usage, but it would serve your purpose.
I would not suggest using the OpenSSL RSA-PSS support as it is. The test cases show that it is validating improper tokens, and you don't want that.
from libjwt.
I am not directly generating rsa key pair by using openssl. Actually, the public key is getting generated in C code from exponent(e) and modulus(n) values of a jwks data and it is in simple RSA format, Not in RSA_PSS format. I have to look for this conversion from RSA to RSA_PSS format in C.
from libjwt.
Since you're creating the key from a JWK, you should be able to create the key as RSA_PSS using the values contained in it. Can you show me the C code that you use to do this? Maybe I can help with that.
from libjwt.
This is my C code
BIGNUM* bignum_base64_decode(const char* base64bignum) {
BIGNUM* bn = NULL;
size_t base64_input_length = strlen(base64bignum);
size_t output_length = (base64_input_length / 4) * 3; // Estimate the output length
unsigned char* output = (unsigned char *)calloc(1, (output_length + 1) * sizeof(char));
int result = base64_decode(base64bignum, base64_input_length, output, &output_length);
if (result == 0) {
bn = BN_bin2bn(output, output_length, NULL);
}
free(output);
return bn;
}
int generate_pubkey_from_exponent_and_modulus(char* exponent, char* modulus, EVP_PKEY** pubkey){
BIGNUM *n = bignum_base64_decode(modulus);
BIGNUM *e = bignum_base64_decode(exponent);
if (!e || !n) {
ERROR("Error: Invalid encoding for public exponent or modulus\n");
return -1;
}
if (e && n) {
EVP_PKEY* pRsaKey = EVP_PKEY_new();
RSA* rsa = RSA_new();
if (!RSA_set0_key(rsa, n, e, NULL)) {
ERROR("Error: Failed to set RSA key components");
BN_free(n);
BN_free(e);
RSA_free(rsa);
return -1;
}
EVP_PKEY_assign_RSA(pRsaKey, rsa);
*pubkey = pRsaKey;
return 0;
} else {
if (n) BN_free(n);
if (e) BN_free(e);
return -1;
}
}
from libjwt.
I think something like this would work:
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA_PSS, NULL);
OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new();
OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, n);
OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, e);
OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(param_bld);
EVP_PKEY_fromdata_init(ctx);
EVP_PKEY *pkey = NULL;
EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params);
EVP_PKEY_CTX_free(ctx);
from libjwt.
looks like OSSL_PARAM_BLD these kind of code is present only in openssl 3.x
but my requirement is in 1.1.x
from libjwt.
Maybe:
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA_PSS, NULL);
EVP_PKEY_keygen_init(ctx);
EVP_PKEY_keygen(ctx, &pRsaKey);
EVP_PKEY_assign_RSA(pRsaKey, rsa);
from libjwt.
this is also generating same RSA key which my code generates already. Look at the below piece:
int generate_pubkey_from_exponent_and_modulus(char* exponent, char* modulus, EVP_PKEY** pubkey) {
BIGNUM *n = bignum_base64_decode(modulus);
BIGNUM *e = bignum_base64_decode(exponent);
if (!e || !n) {
printf("Error: Invalid encoding for public exponent or modulus\n");
return -1;
}
if (e && n) {
EVP_PKEY* pRsaKey = EVP_PKEY_new();
RSA* rsa = RSA_new();
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA_PSS, NULL);
EVP_PKEY_keygen_init(ctx);
EVP_PKEY_keygen(ctx, &pRsaKey);
if (!RSA_set0_key(rsa, n, e, NULL)) {
printf("\nError: Failed to set RSA key components");
BN_free(n);
BN_free(e);
RSA_free(rsa);
return 1;
}
EVP_PKEY_assign_RSA(pRsaKey, rsa);
*pubkey = pRsaKey;
return 0;
}
else {
if (n) BN_free(n);
if (e) BN_free(e);
return -1;
}
}
This complete piece generates the same key as I have already. And if I remove
if (!RSA_set0_key(rsa, n, e, NULL)) {
printf("\nError: Failed to set RSA key components");
BN_free(n);
BN_free(e);
RSA_free(rsa);
return 1;
}
this piece of code, the output becomes,
-----BEGIN PUBLIC KEY-----
MBQwDQYJKoZIhvcNAQEBBQADAwAwAA==
-----END PUBLIC KEY-----
from libjwt.
Can you add this line after assigning the RSA key:
printf("PKEY ID: %d\n", EVP_PKEY_id(pRsaKey));
And show me what it outputs? The difference should be the key type (RSA_PSS instead of RSA).
from libjwt.
And, May I know why does RSA_PSS type of key mandatory for PS384?
from libjwt.
Can you add this line after assigning the RSA key:
printf("PKEY ID: %d\n", EVP_PKEY_id(pRsaKey));
And show me what it outputs? The difference should be the key type (RSA_PSS instead of RSA).
PKEY ID: 6
from libjwt.
By definition the PS algorithms are meant to use RSASSA-PSS keys. You can comment out this check in jwt_verify_sha_pem()
:
if (pkey_type != type)
VERIFY_ERROR(EINVAL);
But as I stated earlier, this would be against the specs.
from libjwt.
yeah. I have tried commenting out this check already. It is working. But it expects key type id should be 912. Isn't it? How should I proceed now?
from libjwt.
You might also try adding:
EVP_PKEY_set_alias_type(pRsaKey, EVP_PKEY_RSA_PSS);
After assigning the RSA key to the pRsaKey.
from libjwt.
didnt help.
EVP_PKEY_assign_RSA(pRsaKey, rsa);
printf("PKEY ID: %d\n", EVP_PKEY_id(pRsaKey));
EVP_PKEY_set_alias_type(pRsaKey, EVP_PKEY_RSA_PSS);
printf("PKEY ID: %d\n", EVP_PKEY_id(pRsaKey));
PKEY ID: 6
PKEY ID: 6
from libjwt.
Seems like with your restrictions on the PKEY creation and OpenSSL 1.1 usage, you'll have to continue using the workaround to LibJWT to disregard the type check in the validation code.
from libjwt.
We are trying to fix it. Will update you on this.
and one more is, regarding the token creation and verifying the same in JWT.io site. I have found few things, in your examples, there is a file called main-gen.c which generates token, isn't it? I tried generating a token which is of RS256 type and took its relevant public key also from your tests folder. This token is getting verified in jwt.io.
In the same way, I just modified the algorithm type to PS256/PS384 and so, generated token is not proper which misses signature in it. Getting below output:
jwtgen: privkey private_key.pem algorithm (null)
priv key loaded private_key.pem (1703)!
{
"alg": "none"
}
.
{
"iat": 1689314617
}
jwt algo (null)!
eyJhbGciOiJub25lIn0.eyJpYXQiOjE2ODkzMTQ2MTd9.
and I am using below set of commands to create a JWT token which I shared already in one of the above comments,
To create a JWT token with OpenSSL, you can follow these steps:
Step 1: Generate an RSA key pair with PS384 algorithm:
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private_key.pem -out public_key.pem
Step 2: Create the JWT header and payload as JSON:
HEADER='{"alg":"PS384","typ":"JWT"}'
PAYLOAD='{"sub":"1234567890","name":"John Doe","iat":1516239022}'
Step 3: Base64-encode the header and payload:
BASE64_HEADER=$(echo -n $HEADER | base64 | tr -d '=' | tr '/+' '_-')
BASE64_PAYLOAD=$(echo -n $PAYLOAD | base64 | tr -d '=' | tr '/+' '_-')
Step 4: Create the JWT token by signing the base64-encoded header and payload using the private key:
SIGNATURE=$(echo -n "$BASE64_HEADER.$BASE64_PAYLOAD" | openssl dgst -sha384 -sign private_key.pem | base64 | tr -d '=' | tr '/+' '_-')
JWT_TOKEN="$BASE64_HEADER.$BASE64_PAYLOAD.$SIGNATURE"
echo $JWT_TOKEN
Token that is produced by these steps, is not getting verified on JWT.io
but decoding is fine.
Any idea on this.
from libjwt.
EVP_PKEY_set_type(pRsaKey, EVP_PKEY_RSA_PSS);
this function sets the key type properly. But after done this, looks like pRsaKey gets corrupted. Not able to do any further operation. I tried writing this key to a file like,
EVP_PKEY_assign_RSA(pRsaKey, rsa);
EVP_PKEY_set_type(pRsaKey, EVP_PKEY_RSA_PSS);
FILE* fp = fopen("pubnew.key", "w");
if (!fp) {
printf("Failed to open file for writing");
return 0;
}
ret = PEM_write_PUBKEY(fp, pRsaKey);
This leads to segmentation fault.
Then instead of using pRsaKey directly, I have created another object and copied it contents and using it like,
EVP_PKEY_assign_RSA(pRsaKey, rsa);
EVP_PKEY_set_type(pRsaKey, EVP_PKEY_RSA_PSS);
EVP_PKEY *pubkey = EVP_PKEY_new();
EVP_PKEY_copy_parameters(*pubkey, pRsaKey);
FILE* fp = fopen("pubnew.key", "w");
if (!fp) {
printf("Failed to open file for writing");
return 0;
}
ret = PEM_write_PUBKEY(fp, pubkey );
fclose(fp);
Same segmentation fault when writing. Any idea?
from libjwt.
I explained before that the current code generates bad signatures for the PS algos unless you use GnuTLS instead of OpenSSL. I’m working on it.
from libjwt.
@benmcollins I have fixed issue in creating RSA_PSS key. now able to verify the token successfully. Just a simple change. Replaced
EVP_PKEY_assign_RSA(pRsaKey, rsa); by
EVP_PKEY_assign(pRsaKey, EVP_PKEY_RSA_PSS, rsa); in key generation.
Thanks for all the support. When can I expect the release?
from libjwt.
Glad you were able to get this working.
As soon as I fix RSA_PSS signing with OpenSSL, I'll release a new version.
from libjwt.
Hi ben, when can we expect the release?
from libjwt.
I should be able to finish things up this weekend.
from libjwt.
thanks for your update.
from libjwt.
Any updates ben?
from libjwt.
Things are moving along, but took longer than expected. Still working on it.
from libjwt.
thanks for the update. We are packaging code for debian and this code is causing test to fail in the libjwt-gnutls-dev package
from libjwt.
I strongly suggest backing down to 1.15.3. The 1.16.0 release was withdrawn and is not official.
from libjwt.
I am not the package maintainer, but I will forward the suggestion along. Thanks.
from libjwt.
Related Issues (20)
- Audience check
- Slurmctld gives error on OpenSuse Leap 15.3 : fatal: plugin_load_and_link: Plugin loading failed due to missing symbols. Plugin is corrupted. HOT 5
- config.h is missing HOT 1
- Setup libjwt and JWT auth on existing HPC Cluster installed from OpenHPC Repo generate errors HOT 9
- OpenSSL 3? HOT 2
- NEWS file? HOT 3
- Compile error in C++ code HOT 3
- jansson.h is missing HOT 4
- Compiling under SSL 3.x triggers warnings. HOT 4
- fatal error: jwt.h: No such file or directory HOT 2
- missing `libjwt-1.15.3.tar.gz` for 1.15.3 release HOT 1
- JWT: jwt_encode_str() function return only three characters. HOT 4
- ./confugre not working HOT 1
- Correct package on Debian 12 HOT 6
- Is 1.16.0 stable? HOT 2
- Upgrade `m4/doxygen.m4` to `ax_prog_doxygen.m4` from GNU Autoconf Archive? HOT 2
- Failed to parse JWT HOT 1
- Error parsing fractional values in JWT exp HOT 3
- Native windows build HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from libjwt.