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:
Interface between Joken and JOSE for signing and verifying tokens.
In the future we plan to keep this interface but make it pluggable for other crypto
implementations like using only standard `:crypto` and `:public_key` modules. So,
**avoid** depending on the inner structure of this module.
"""
alias JOSE.{JWK, JWS, JWT}
@hs_algorithms ["HS256", "HS384", "HS512"]
@rs_algorithms ["RS256", "RS384", "RS512"]
@es_algorithms ["ES256", "ES384", "ES512"]
@ps_algorithms ["PS256", "PS384", "PS512"]
@eddsa_algorithms ["Ed25519", "Ed25519ph", "Ed448", "Ed448ph", "EdDSA"]
@map_key_algorithms @rs_algorithms ++ @es_algorithms ++ @ps_algorithms ++ @eddsa_algorithms
@algorithms @hs_algorithms ++ @map_key_algorithms
@typedoc "A key may be an octet or a map with parameters according to JWK (JSON Web Key)"
@type key :: binary() | map()
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 ).