Have anyone tried signing JWT with ES512 algorithm?

Has anyone managed to sign JWT with ES512 algorithm successfully? I have tried to look for libraries to do this but was not successful

I generated my keypair using

openssl ecparam -genkey -name secp521r1 -noout -out ec521-key-pair.pem
openssl ec -in ec521-key-pair.pem -pubout -out ec521-public-key.pem

Tried using yajwt | Hex

private_key = File.read("ec521-key-pair.pem")

opts = %{
  alg: "ES512",
  key: private_key
}

JWT.sign(
  %{
    jti: Ecto.UUID.generate(),
    iss: "client",
    aud: "server",
    nbf: DateTime.now!("Etc/UTC") |> DateTime.to_unix(),
    iat: DateTime.now!("Etc/UTC") |> DateTime.to_unix(),
    exp: (DateTime.now!("Etc/UTC") |> DateTime.to_unix()) + expiry
  },
  opts
)

Unsuccessful

** (ErlangError) Erlang error: {:badarg, {'pkey.c', 362}, 'Couldn\'t get ECDSA private key'}:

  * 4th argument: Couldn't get ECDSA private key

    (crypto 5.1.2) crypto.erl:1458: :crypto.sign/5
    (yajwt 1.4.1) lib/jwt/algorithm/ecdsa.ex:27: JWT.Algorithm.Ecdsa.sign/3
    (yajwt 1.4.1) lib/jwt/jws.ex:42: JWT.Jws.do_sign/3
    (yajwt 1.4.1) lib/jwt/jws.ex:21: JWT.Jws.sign/3
    .iex.exs:20: Foo.foo/0
    iex:1: (file)

I would recommend trying Joken GitHub - joken-elixir/joken: Elixir JWT library

I use it, albeit with a different signing algorithm, but the one you want to use is also supported:

2 Likes

You need to load and decode the pem. File.read will just return a tuple. Unfortunately yajwt only has this util function for RSA. If you want to continue using the library the following should work (not tested, but based on the readme example):

[entry] = :public_key.pem_decode(File.read!("ec521-key-pair.pem"))
{:ok, private_key} = :public_key.pem_entry_decode(entry)

There are a lot of JWT libraries as well, the most popular ones being JOSE and Joken as @hubertlepicki mentioned. I even rolled my own with Erlang in Assent (but you def shouldn’t do that :smile:).