-
Notifications
You must be signed in to change notification settings - Fork 104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Not able to verify using RSA public key #19
Comments
@pavananms I believe there are two issues with the example you provided.
A public RSA key is essentially the %% secret key: n
<<"v5SM4zitKoxHsM6bmZepdTk6iYYAo_7Beh3t-nLKgJD1_BIyyIB2cKGY12wb81Cz0DRACvtfHsJKwiZb_MG8J5IruWvIeQjcz2xdCcd8JuKLN25HLOgRk_zegmZju4xTuJqe9kA6z0Ow4Xv5OFjBU9COuIRzjmENpZrfZXy_QNANVdnvx9Yc_OzjfW0eV91ay2nXVQ9YTprdcgezPnrZSZsol6hw5Zgg6N7ptCN-N_-S8AgLyRnesLFYsodkNQeDs3jv73MfLkB7pU_HVlK2Cob3nwKANVC1mgVD5-MV98D_t_AtuID6cfRy25UBAPHd-d7hOYne0iM_rhWF8z8DLw">>
%% public key: n
<<"ie4OsY4wbR9RSlxqYfY26ZA7dj_eK9kCmUEKCRZnCsPvOb0d3ZLySFbe7x5kQJAHgswR-AcxZXSHNsLhwA1bb5oul7TTa4ea4Z65ivFentzQJ87BBi8AGiGRO6laOLsRbv_9rd9WCtpNkyCMNflqzMO707g7GpbnyCzm0bPQxQmVvY6STCm2apmIgRs59KRsygLnhdDAWc4Gzajoc4Zbvpcd3IpEjSeqDn806lDLAtCKTAzU2IDc26jK38eJFhz2BA66QEOADn9CFEIP2afpVbWVbf-6Nb-OeBL0A_CsIR7RA6pOCMJTDi-0dG1jFnttVkR_gnceXcruOQmQSq0R_Q">> If we take the {
"keys": [
{
"kty": "RSA",
"e": "AQAB",
"use": "sig",
"kid": "mak1",
"n": "v5SM4zitKoxHsM6bmZepdTk6iYYAo_7Beh3t-nLKgJD1_BIyyIB2cKGY12wb81Cz0DRACvtfHsJKwiZb_MG8J5IruWvIeQjcz2xdCcd8JuKLN25HLOgRk_zegmZju4xTuJqe9kA6z0Ow4Xv5OFjBU9COuIRzjmENpZrfZXy_QNANVdnvx9Yc_OzjfW0eV91ay2nXVQ9YTprdcgezPnrZSZsol6hw5Zgg6N7ptCN-N_-S8AgLyRnesLFYsodkNQeDs3jv73MfLkB7pU_HVlK2Cob3nwKANVC1mgVD5-MV98D_t_AtuID6cfRy25UBAPHd-d7hOYne0iM_rhWF8z8DLw"
}
]
} This public key works as expected, as shown below: %% Secret Key
SecretKeys = <<"{\"keys\":[{\"kty\":\"RSA\",\"d\":\"BEwStO4KhE_NM9wOhW1vcZ-s_nSxAvyt3k1ZjyqP_D5EJjlKRlELVw9o3DwijFydC-iAHz7wLUJyZtRxb8PwsnqG3IvcXUqjmUt28sc0s7KVKNMiaZFzA3zCiO4_Am_tWNCvDBr4trlv-D7NokPrYjPlX6Io7WKj6bkFlcMsjwmRr60VnUplrt0YWQmSZa18Nn2Xg4f3U0qMVM9HsSztegayZlAQJhVQT3Z_FP9MXcnxNP8RCADcfSD7CvbwHDp3ttxLN89qEiUVezyjmGSmrnCOVEcDdy2RDbTbxToAEBbFgIXIEIXTpAT60mi04e3HwCe8ZH1Lk5Z-GxNSpVnqgQ\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"mak1\",\"alg\":\"RS256\",\"n\":\"v5SM4zitKoxHsM6bmZepdTk6iYYAo_7Beh3t-nLKgJD1_BIyyIB2cKGY12wb81Cz0DRACvtfHsJKwiZb_MG8J5IruWvIeQjcz2xdCcd8JuKLN25HLOgRk_zegmZju4xTuJqe9kA6z0Ow4Xv5OFjBU9COuIRzjmENpZrfZXy_QNANVdnvx9Yc_OzjfW0eV91ay2nXVQ9YTprdcgezPnrZSZsol6hw5Zgg6N7ptCN-N_-S8AgLyRnesLFYsodkNQeDs3jv73MfLkB7pU_HVlK2Cob3nwKANVC1mgVD5-MV98D_t_AtuID6cfRy25UBAPHd-d7hOYne0iM_rhWF8z8DLw\"}]}">>.
[SecretKey | _] = [K || K = #{<<"kid">> := <<"mak1">>} <- maps:get(<<"keys">>, jose:decode(SecretKeys))].
SecretJWK = jose_jwk:from_map(SecretKey).
%% Sign
JWS = #{
<<"alg">> => <<"RS256">>,
<<"kid">> => <<"mak1">>
}.
JWT = #{
<<"iss">> => <<"joe">>,
<<"exp">> => 1300819380,
<<"http://example.com/is_root">> => true
}.
{_, SignedBinary} = jose_jws:compact(jose_jwt:sign(SecretJWK, JWS, JWT)).
% SignedBinary = <<"eyJhbGciOiJSUzI1NiIsImtpZCI6Im1hazEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UifQ.QYPJNennVKwYYEtSIASrSNlKMjyd3MmwuEcb1Q03WUz1kLBzXMkxTO2W_u7XGKSbI9QhBXi-09Vhxc36yJfgyty9KYPsojX0nN6gylFA6yQhhOpuPeRwHbjGOrdEhipS3wC6KC7tSKM5YjQFhRDUJlzVOYubqn3xLcBvhgDVdUMbzEbCQJXjHKezwQ591KPJTgmxONu7jGcAr1m6m1Xf0cXrfdLuO8d89R7Z5tXbMS57E-hcctiJP3IAR_eUB5LQjXI-ERtJzq8SHV2hlIiRx_Evw07tf3JaPcX8wMoZsCE-VU-heRKWkKqUPqMrZN67H1WA0XJulA4TlGWp_7_Seg">>.
%% Public Key
PublicKeys = <<"{\"keys\":[{\"kty\":\"RSA\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"mak1\",\"n\":\"v5SM4zitKoxHsM6bmZepdTk6iYYAo_7Beh3t-nLKgJD1_BIyyIB2cKGY12wb81Cz0DRACvtfHsJKwiZb_MG8J5IruWvIeQjcz2xdCcd8JuKLN25HLOgRk_zegmZju4xTuJqe9kA6z0Ow4Xv5OFjBU9COuIRzjmENpZrfZXy_QNANVdnvx9Yc_OzjfW0eV91ay2nXVQ9YTprdcgezPnrZSZsol6hw5Zgg6N7ptCN-N_-S8AgLyRnesLFYsodkNQeDs3jv73MfLkB7pU_HVlK2Cob3nwKANVC1mgVD5-MV98D_t_AtuID6cfRy25UBAPHd-d7hOYne0iM_rhWF8z8DLw\"}]}">>.
[PublicKey | _] = [K || K = #{<<"kid">> := <<"mak1">>} <- maps:get(<<"keys">>, jose:decode(PublicKeys))].
PublicJWK = jose_jwk:from_map(PublicKey).
%% Verify
jose_jwt:verify_strict(PublicJWK, [<<"RS256">>], SignedBinary).
{true,#jose_jwt{fields = #{<<"exp">> => 1300819380,
<<"http://example.com/is_root">> => true,
<<"iss">> => <<"joe">>}},
#jose_jws{alg = {jose_jws_alg_rsa_pkcs1_v1_5,'RS256'},
b64 = undefined,
fields = #{<<"kid">> => <<"mak1">>,<<"typ">> => <<"JWT">>}}} If PublicJWK = jose_jwk:to_public(SecretJWK). would have worked for converting your secret to a public key. However, as I mentioned at the beginning, the library doesn't currently support " |
Hi @potatosalad , Also, can you address that last question i mentioned above.? Can we verify whether a token is valid or invalid by looking at the different attributes in the claim? |
@pavananms Sorry I neglected to answer your questions earlier:
In most cases, there are 8 numbers that make up a RSA key:
Yes, but there is nothing built into Now = erlang:system_time(milli_seconds),
try jose_jwt:peek_payload(SignedBinary) of
JWT = #jose_jwt{fields = #{
<<"exp">> := Exp, % the JWT must have an expiration time
<<"sub">> := _, % the JWT must have a subject claim
<<"iss">> := <<"Issuer">>, % whom the JWT needs to have been issued by
<<"aud">> := <<"Audience">> % to whom the JWT is intended for
}}
when is_integer(Exp)
andalso (Exp - Now) < (30 * 60 * 1000) % but the expiration time can't be too crazy
andalso (Exp + (30 * 1000)) > Now -> % allow some leeway in validating time based claims to account for clock skew
% verify the signature with the public key
case jose_jwt:verify_strict(PublicJWK, [<<"RS256">>], SignedBinary) of
{true, JWT, _JWS} ->
{ok, JWT};
_ ->
error
end;
_ ->
error
catch
_:_ ->
error
end. |
* Enhancements * Improved handling of RSA private keys in SMF (Straightforward Method) form to CRT (Chinese Remainder Theorem) form, see #19. This is especially useful for keys produced by Java programs using the RSAPrivateKeySpec API as mentioned in Section 9.3 of RFC 7517. * Updated EdDSA operations to comply with draft 02 of draft-ietf-jose-cfrg-curves-02.
@pavananms RSA keys from Java in SMF format are better supported as of jose 1.7.7 (see entry in changelog). |
Ok, I will look into this .Thank you so much. |
* Enhancements * Improved handling of RSA private keys in SMF (Straightforward * Method) form to CRT (Chinese Remainder Theorem) form, see * potatosalad/erlang-jose#19 This is especially useful for keys * produced by Java programs using the `RSAPrivateKeySpec` API as * mentioned in Section 9.3 of RFC 7517: * https://tools.ietf.org/html/rfc7517#section-9.3 * Updated EdDSA operations to comply with draft 04 of * https://tools.ietf.org/html/draft-ietf-jose-cfrg-curves-04. * Fixes * Fixed compression encoding bug for `{"zip":"DEF"}` operations * (thanks to @amadden734 see #3)
Hi @potatosalad
We have an authentication server where a public key will be hosted. So we will get the public key from a url like :- http://localhost/jwks.json
The public key will be a json of the form;
We tried the following code sample to verify a jwt ;
And if we verify the JWK by ;
It gets verified properly and gives {true, _, _}.
But if we use the public key:
And tried;
This is verified false.
How can we verify with public key?
Also, can you please explain the details of how the verify function works?
What all does it check?
Can we verify whether the token claim contains attributes like, a valid expiration time, a subject etc.?
An equivalent java example would be ;
The text was updated successfully, but these errors were encountered: