Skip to content
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

Could not recognize the signer algo #223

Closed
vans163 opened this issue Mar 28, 2019 · 13 comments
Closed

Could not recognize the signer algo #223

vans163 opened this issue Mar 28, 2019 · 13 comments

Comments

@vans163
Copy link

vans163 commented Mar 28, 2019

Joken.Signer.create("RS256", "secret")

**** (Joken.Error) Couldn't recognize the signer algorithm.

Possible values are:

["HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "ES256", "ES384", "ES512", "PS256", "PS384", "PS512", "Ed25519", "Ed25519ph", "Ed448", "Ed448ph"]

    lib/joken/signer.ex:93: Joken.Signer.create/3
**
@victorolinasc
Copy link
Collaborator

This is because the algorithm RS*** uses public/private keys for verifying/signing a token.

More info can be seen on the asymmetric crypto guide here.

The error message could be tweaked to be more specific. I'll keep this open until I get around it.

@autodidaddict
Copy link

I'm having the same problem. I want to create an Ed25519 signer to verify tokens but I can't figure out how to create it, the create function . just gives me that error about an unrecognized signer algorithm.

@victorolinasc
Copy link
Collaborator

Hi @autodidaddict

The Edwards curves family of algorithms are not built-in and need some extra dependencies to work. This is the way JOSE works. More information may be found here: https://github.com/potatosalad/erlang-jose/blob/master/ALGORITHMS.md

Although OTP now supports edwards curves (OTP 21 with a recent OpenSSL/BoringSSL) this detection is not built-in in JOSE.

We are planning on providing our own implementation of JWA in the future to make it more easily pluggable but time is never a comodity unfortunately.

@vans163 Did that solve your issue? Can I close this one?

@autodidaddict
Copy link

@victorolinasc I'm not native to the Elixir ecosystem so I'm struggling a bit with the solution here. I added libdecaf as a dependency to my project, but I apparently can't compile libsodium when I add it as a dependency. Do I need both? With just libdecaf present I still get the same error.

@victorolinasc
Copy link
Collaborator

For Ed25519 you need both. They are C libraries that JOSE binds to in order to delegate the execution of this algorithm.

Unfortunately it is a bit outside of my scope too as those libraries have themselves other dependencies that are OS dependent.

@databrecht
Copy link

Is it a similar error when I receive:
iex(3)> signer = Joken.Signer.create("RS512", %{"pem" => pem})
** (FunctionClauseError) no function clause matching in :jose_jwk.from_pem/1

Tried to pass it as a string or pass it through JOSE.JWK.from_pem_file first. Both don't work.
Do I need to install something first?

@victorolinasc
Copy link
Collaborator

@bderooms this is a different issue... Probably related to your pem variable. It seems that it is not a String.t() in your case.

For instance:

:jose_jwk.from_pem(123456)
** (FunctionClauseError) no function clause matching in :jose_jwk.from_pem/1    
    
    The following arguments were given to :jose_jwk.from_pem/1:
    
        # 1
        123456
    
    (jose) src/jose_jwk.erl:371: :jose_jwk.from_pem/1

Pem should contain a valid PEM encoded key.

@victorolinasc
Copy link
Collaborator

@vans163 I'll close this issue for now. If anything, please re-open this. THanks!

@vans163
Copy link
Author

vans163 commented Jul 8, 2019

I stopped using Joken and just implemented the signature check myself, I needed it for JWT validation. So cannot comment if its fixed..

    def validate_jwt(nil), do: nil
    def validate_jwt(token) do
        [headerb, payloadb, signatureb] = String.split(token, ".")
        header = Base.url_decode64!(headerb, padding: false) |> JSX.decode!
        payload = Base.url_decode64!(payloadb, padding: false) |> JSX.decode!
        signature = Base.url_decode64!(signatureb, padding: false)

        true = Map.fetch!(header,"alg") == "RS256"
        true = Map.fetch!(payload, "iss") == "https://securetoken.google.com/"
        isExpired = :os.system_time(1) >= Map.fetch!(payload, "exp")
        case :persistent_term.get({:kid, Map.fetch!(header,"kid")}, nil) do
            nil -> 
                jwt_google_cert()
                nil
            %{exponent: exponent, modulus: modulus} ->
                msg = headerb<>"."<>payloadb
                if :crypto.verify(:rsa, :sha256, msg, signature, [exponent,modulus]) and !isExpired do
                    Map.fetch!(payload, "user_id")
                end
        end
    end

The hard part was pulling the exponent and modulus out the google cert.

@adamu
Copy link

adamu commented May 9, 2020

The error message could be tweaked to be more specific. I'll keep this open until I get around it.

I've just run in to this. The error is especially confusing, because the list of supported algorithms includes the algorithm that has been rejected.

edit: I managed to get this working directly with JOSE:

private_key = JOSE.JWK.from_pem_file("private_key.pem")
jwt_payload = %{hello: "world"}
{_, jwt} = JOSE.JWT.sign(private_key, %{"alg" => "RS256"}, jwt_payload) |> JOSE.JWS.compact()

@victorolinasc
Copy link
Collaborator

@adamu I am curious as to which error you were getting with Joken. If possible can you paste a simple example?

For instance:

pem = File.read!("private_key.pem")
signer = Joken.Signer.create("RS256", %{"pem" => pem})

Does that not work for you?

@adamu
Copy link

adamu commented May 31, 2022

It was two years ago, let me see... I just tried your suggestion and it works. It's possible I was passing the binary directly instead of a map. If I do that, the error message does say that a map is required:

Joken.Signer.create("RS256", pem)

** (Joken.Error) A map was expected for the key parameter in the signer creation.
This is mandatory for: ["RS256", "RS384", "RS512", "ES256", "ES384", "ES512", "PS256", "PS384", "PS512", "Ed25519", "Ed25519ph", "Ed448", "Ed448ph"].

(joken 2.4.1) lib/joken/signer.ex:100: Joken.Signer.create/3

However, on the version at the time, 2.2.0. it doesn't:

** (Joken.Error) Couldn't recognize the signer algorithm.

Possible values are:

["HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "ES256", "ES384", "ES512", "PS256", "PS384", "PS512", "Ed25519", "Ed25519ph", "Ed448", "Ed448ph"]

(joken 2.2.0) lib/joken/signer.ex:93: Joken.Signer.create/3

Looks like it was resolved in #277.

@victorolinasc
Copy link
Collaborator

SOrry @adamu ! I was trolled by email notifications here ...

Someone commented and then deleted here... I got the email, came here to check and thought it was you heheh sorry about this!

THanks for confirming the fix :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants