ES256 string encryption


I’m working on a simple ES256 string encryption, however I’m hitting a wall using JOSE (also tried doing it using Joken). I am trying to sign a url string to send to Apple’s static map snapshot service (found here).

Here are my simplified steps:

    mapkitServer = ""
    snapshotPath = "/api/v1/snapshot?"
    query = "center=madison+square+garden"
    keys = "&teamId=#{@team_id}&keyId=#{@key_id}"
    completePath = "#{snapshotPath}#{query}#{keys}"
    privateKey = JOSE.JWK.from_pem_file("authkey.p8")
    {_, token} = JOSE.JWK.sign(completePath, privateKey) |> JOSE.JWS.compact()
    # also tried signed_payload = JOSE.JWS.sign(privateKey, completePath, %{ "alg" => "ES256" }) |> JOSE.JWS.compact |> elem(1)
    signature = token |> Base.url_encode64(padding: false)
    # also tried jose_signed = :jose_base64url.encode(token)
    finalUrl = "#{mapkitServer}#{completePath}&signature=#{signature}"

I’ve used JOSE in the past with different algorithms with no issues, however I can’t get a valid response going this route for the ES256 signing. To make sure I’m not going crazy I’ve got this working in both a NodeJS and C++ implementation.

Any help to make sure I’m not missing anything obvious is much appreciated.


I don’t see any mention of JWS in Apple’s documentation, I think they are looking for a raw ECDSA signature. What you want is probably:

:public_key.sign(completePath, :sha256, priv)
|> Base.url_encode64(padding: false)

Where priv is the raw private key in Erlang record format. If you want to keep using JOSE for reading the key you could use priv = JOSE.JWK.to_key(privateKey) |> elem(1). Or you could use x509 instead: priv =!("authkey.p8") |> X509.PrivateKey.from_pem!().

1 Like

Ah, that was a silly oversight on my end. Thank you so much, that worked. Hadn’t run into x509, great library.

Thank you,