• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..01-Dec-2021-

examples/H01-Dec-2021-276190

include/H01-Dec-2021-245110

lib/H01-Dec-2021-3,4992,761

priv/H01-Dec-2021-2821

src/H01-Dec-2021-19,26414,730

.formatter.exsH A D01-Dec-2021122 65

ALGORITHMS.mdH A D01-Dec-20217.7 KiB4640

CHANGELOG.mdH A D01-Dec-202117.9 KiB451344

LICENSE.mdH A D01-Dec-20211.1 KiB2218

MakefileH A D01-Dec-20211.7 KiB5443

README.mdH A D01-Dec-202123 KiB559434

build.configH A D01-Dec-2021796 5143

erlang.mkH A D01-Dec-2021249.5 KiB7,7416,386

mix.exsH A D01-Dec-20212 KiB7365

mix.lockH A D01-Dec-20213.1 KiB1615

rabbitmq-mix.mkH A D01-Dec-2021754 224

rebar.configH A D01-Dec-2021159 76

rebar.lockH A D01-Dec-20214 21

README.md

1# JOSE
2
3[![Build Status](https://travis-ci.org/potatosalad/erlang-jose.svg?branch=master)](https://travis-ci.org/potatosalad/erlang-jose) [![Hex.pm](https://img.shields.io/hexpm/v/jose.svg)](https://hex.pm/packages/jose)
4
5JSON Object Signing and Encryption (JOSE) for Erlang and Elixir.
6
7## Installation
8
9Add `jose` to your project's dependencies in `mix.exs`
10
11```elixir
12defp deps() do
13  [
14    {:jose, "~> 1.11"}
15  ]
16end
17```
18
19If you are using deployment tools (`exrm`, etc.) and your app depends
20on `jose` directly, you will need to include `jose` in your
21applications list in `mix.exs` to ensure they get compiled into your
22release:
23
24```elixir
25def application() do
26  [
27    mod: {YourApp, []},
28    applications: [:jose]
29  ]
30end
31```
32
33Add `jose` to your project's dependencies in your `Makefile` for [`erlang.mk`](https://github.com/ninenines/erlang.mk) or the following to your `rebar.config`
34
35```erlang
36{deps, [
37  {jose, ".*", {git, "git://github.com/potatosalad/erlang-jose.git", {branch, "master"}}}
38]}.
39```
40
41#### JSON Encoder/Decoder
42
43You will also need to specify either [jiffy](https://github.com/davisp/jiffy), [jsone](https://github.com/sile/jsone), [jsx](https://github.com/talentdeficit/jsx), [ojson](https://github.com/potatosalad/erlang-ojson), [Poison](https://github.com/devinus/poison), or [Jason](https://github.com/michalmuskala/jason) as a dependency.
44
45For example, with Elixir and `mix.exs`
46
47```elixir
48defp deps() do
49  [
50    {:jose, "~> 1.11"},
51    {:ojson, "~> 1.0"}
52  ]
53end
54```
55
56Or with Erlang and `rebar.config`
57
58```erlang
59{deps, [
60  {jose, ".*", {git, "git://github.com/potatosalad/erlang-jose.git", {branch, "master"}}},
61  {ojson, ".*", {git, "git://github.com/potatosalad/erlang-ojson.git", {branch, "master"}}}
62]}.
63```
64
65`jose` will attempt to find a suitable JSON encoder/decoder and will try to use (in order) ojson, Jason, Poison, jiffy, jsone, or jsx.
66
67You may also specify a different `json_module` as an application environment variable to `jose` or by using `jose:json_module/1` or `JOSE.json_module/1`.
68
69#### ChaCha20/Poly1305 Support
70
71ChaCha20/Poly1305 encryption and one-time message authentication functions are experimentally supported based on [RFC 7539](https://tools.ietf.org/html/rfc7539).
72
73Fallback support for `ChaCha20/Poly1305` encryption and `Poly1305` signing is also provided.  See [`crypto_fallback`](#cryptographic-algorithm-fallback) below.
74
75External support is also provided by the following libraries:
76
77 * [libsodium](https://github.com/potatosalad/erlang-libsodium) - `ChaCha20/Poly1305` encryption and `Poly1305` signing
78
79Other modules which implement the `jose_chacha20_poly1305` behavior may also be used as follows:
80
81```elixir
82# ChaCha20/Poly1305
83JOSE.chacha20_poly1305_module(:libsodium)                  # uses a fast Erlang port driver for libsodium
84JOSE.chacha20_poly1305_module(:jose_jwa_chacha20_poly1305) # uses the pure Erlang implementation (slow)
85```
86
87#### Curve25519 and Curve448 Support
88
89Curve25519 and Curve448 and their associated signing/key exchange functions are supported now that [RFC 8037](https://tools.ietf.org/html/rfc8037) has been published.
90
91Fallback support for `Ed25519`, `Ed25519ph`, `Ed448`, `Ed448ph`, `X25519`, and `X448` is provided.  See [`crypto_fallback`](#cryptographic-algorithm-fallback) below.
92
93External support is also provided by the following libraries:
94
95 * [libdecaf](https://github.com/potatosalad/erlang-libdecaf) - `Ed25519`, `Ed25519ph`, `Ed448`, `Ed448ph`, `X25519`, `X448`
96 * [libsodium](https://github.com/potatosalad/erlang-libsodium) - `Ed25519`, `Ed25519ph`, `X25519`
97
98If both libraries are present, libdecaf will be used by default.  Other modules which implement the `jose_curve25519` or `jose_curve448` behaviors may also be used as follows:
99
100```elixir
101# Curve25519
102JOSE.curve25519_module(:libdecaf)            # uses a fast Erlang NIF for libdecaf
103JOSE.curve25519_module(:jose_jwa_curve25519) # uses the pure Erlang implementation (slow)
104
105# Curve448
106JOSE.curve448_module(:libdecaf)          # uses a fast Erlang NIF for libdecaf
107JOSE.curve448_module(:jose_jwa_curve448) # uses the pure Erlang implementation (slow)
108```
109
110#### SHA-3 Support
111
112SHA-3 is experimentally supported for use with `Ed448` and `Ed448ph` signing functions.
113
114Fallback support for SHA-3 is provided.  See [`crypto_fallback`](#cryptographic-algorithm-fallback) below.
115
116External support for SHA-3 is provided by the [keccakf1600](https://github.com/potatosalad/erlang-keccakf1600) and [libdecaf](https://github.com/potatosalad/erlang-libdecaf) libraries.  If present, keccakf1600 will be used by default.  Other modules which implement the `jose_sha3` behaviors may also be used as follows:
117
118```elixir
119JOSE.sha3_module(:keccakf1600)   # uses a NIF written in C with timeslice reductions
120JOSE.sha3_module(:jose_jwa_sha3) # uses the pure Erlang implementation (slow)
121```
122
123#### Cryptographic Algorithm Fallback
124
125`jose` strives to support [all](#algorithm-support) of the cryptographic algorithms specified in the [JOSE RFCs](https://tools.ietf.org/wg/jose/).
126
127However, not all of the required algorithms are supported natively by Erlang/Elixir.  For algorithms unsupported by the native [`crypto`](http://www.erlang.org/doc/man/crypto.html) and [`public_key`](http://www.erlang.org/doc/man/public_key.html), `jose` has a pure Erlang implementation that may be used as a fallback.
128
129See [ALGORITHMS.md](https://github.com/potatosalad/erlang-jose/blob/master/ALGORITHMS.md) for more information about algorithm support for specific OTP versions.
130
131By default, the algorithm fallback is disabled, but can be enabled by setting the `crypto_fallback` application environment variable for `jose` to `true` or by calling `jose:crypto_fallback/1` or `JOSE.crypto_fallback/1` with `true`.
132
133You may also review which algorithms are currently supported with the `jose_jwa:supports/0` or `JOSE.JWA.supports/0` functions.  For example, on Elixir 1.9.4 and OTP 22:
134
135```elixir
136# crypto_fallback defaults to false
137JOSE.JWA.supports()
138
139[
140  {:jwe,
141   {:alg,
142    ["A128GCMKW", "A128KW", "A192GCMKW", "A192KW", "A256GCMKW", "A256KW",
143     "C20PKW", "ECDH-1PU", "ECDH-1PU+A128GCMKW", "ECDH-1PU+A128KW",
144     "ECDH-1PU+A192GCMKW", "ECDH-1PU+A192KW", "ECDH-1PU+A256GCMKW",
145     "ECDH-1PU+A256KW", "ECDH-1PU+C20PKW", "ECDH-ES", "ECDH-ES+A128GCMKW",
146     "ECDH-ES+A128KW", "ECDH-ES+A192GCMKW", "ECDH-ES+A192KW",
147     "ECDH-ES+A256GCMKW", "ECDH-ES+A256KW", "ECDH-ES+C20PKW",
148     "PBES2-HS256+A128GCMKW", "PBES2-HS256+A128KW", "PBES2-HS384+A192GCMKW",
149     "PBES2-HS384+A192KW", "PBES2-HS512+A256GCMKW", "PBES2-HS512+A256KW",
150     "PBES2-HS512+C20PKW", "RSA-OAEP", "RSA-OAEP-256", "RSA1_5", "dir"]},
151   {:enc,
152    ["A128CBC-HS256", "A128GCM", "A192CBC-HS384", "A192GCM", "A256CBC-HS512",
153     "A256GCM", "C20P"]}, {:zip, ["DEF"]}},
154  {:jwk, {:kty, ["EC", "OKP", "RSA", "oct"]}, {:kty_OKP_crv, []}},
155  {:jws,
156   {:alg,
157    ["ES256", "ES384", "ES512", "HS256", "HS384", "HS512", "PS256", "PS384",
158     "PS512", "Poly1305", "RS256", "RS384", "RS512"]}}
159]
160
161# setting crypto_fallback to true
162JOSE.crypto_fallback(true)
163
164# additional algorithms are now available for use
165JOSE.JWA.supports()
166
167[
168  {:jwe,
169   {:alg,
170    ["A128GCMKW", "A128KW", "A192GCMKW", "A192KW", "A256GCMKW", "A256KW",
171     "C20PKW", "ECDH-1PU", "ECDH-1PU+A128GCMKW", "ECDH-1PU+A128KW",
172     "ECDH-1PU+A192GCMKW", "ECDH-1PU+A192KW", "ECDH-1PU+A256GCMKW",
173     "ECDH-1PU+A256KW", "ECDH-1PU+C20PKW", "ECDH-1PU+XC20PKW", "ECDH-ES",
174     "ECDH-ES+A128GCMKW", "ECDH-ES+A128KW", "ECDH-ES+A192GCMKW",
175     "ECDH-ES+A192KW", "ECDH-ES+A256GCMKW", "ECDH-ES+A256KW", "ECDH-ES+C20PKW",
176     "ECDH-ES+XC20PKW", "PBES2-HS256+A128GCMKW", "PBES2-HS256+A128KW",
177     "PBES2-HS384+A192GCMKW", "PBES2-HS384+A192KW", "PBES2-HS512+A256GCMKW",
178     "PBES2-HS512+A256KW", "PBES2-HS512+C20PKW", "PBES2-HS512+XC20PKW",
179     "RSA-OAEP", "RSA-OAEP-256", "RSA1_5", "XC20PKW", "dir"]},
180   {:enc,
181    ["A128CBC-HS256", "A128GCM", "A192CBC-HS384", "A192GCM", "A256CBC-HS512",
182     "A256GCM", "C20P", "XC20P"]}, {:zip, ["DEF"]}},
183  {:jwk, {:kty, ["EC", "OKP", "RSA", "oct"]},
184   {:kty_OKP_crv,
185    ["Ed25519", "Ed25519ph", "Ed448", "Ed448ph", "X25519", "X448"]}},
186  {:jws,
187   {:alg,
188    ["ES256", "ES384", "ES512", "Ed25519", "Ed25519ph", "Ed448", "Ed448ph",
189     "HS256", "HS384", "HS512", "PS256", "PS384", "PS512", "Poly1305", "RS256",
190     "RS384", "RS512"]}}
191]
192```
193
194#### Unsecured Signing Vulnerability
195
196The [`"none"`](https://tools.ietf.org/html/rfc7515#appendix-A.5) signing algorithm is disabled by default to prevent accidental verification of empty signatures (read about the vulnerability [here](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/)).
197
198If you want to further restrict the signature algorithms allowed for a token, use `JOSE.JWT.verify_strict/3`:
199
200```elixir
201# Signed Compact JSON Web Token (JWT) with HS256
202token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UifQ.shLcxOl_HBBsOTvPnskfIlxHUibPN7Y9T4LhPB-iBwM"
203
204# JSON Web Key (JWK)
205jwk = %{
206  "kty" => "oct",
207  "k" => :jose_base64url.encode("symmetric key")
208}
209
210{verified, _, _} = JOSE.JWT.verify_strict(jwk, ["HS256"], token)
211# {true, _, _}
212
213{verified, _, _} = JOSE.JWT.verify_strict(jwk, ["RS256"], token)
214# {false, _, _}
215```
216
217If you need to inspect the contents of a JSON Web token (JWT) prior to verifying it, use `JOSE.JWT.peek_payload/1` or `JOSE.JWT.peek_protected/1`:
218
219```elixir
220token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UifQ.shLcxOl_HBBsOTvPnskfIlxHUibPN7Y9T4LhPB-iBwM"
221
222payload = JOSE.JWT.peek_payload(token)
223# %JOSE.JWT{fields: %{"exp" => 1300819380, "http://example.com/is_root" => true,
224#    "iss" => "joe"}}
225
226protected = JOSE.JWT.peek_protected(token)
227# %JOSE.JWS{alg: {:jose_jws_alg_hmac, {:jose_jws_alg_hmac, :sha256}},
228#  b64: :undefined, fields: %{"typ" => "JWT"}}
229
230# If you want to inspect the JSON, you can convert it back to a regular map:
231{_, protected_map} = JOSE.JWS.to_map(protected)
232# {_, %{"alg" => "HS256", "typ" => "JWT"}}
233```
234
235You may also enable the `"none"` algorithm as an application environment variable for `jose` or by using `jose:unsecured_signing/1` or `JOSE.unsecured_signing/1`.
236
237```elixir
238# unsecured_signing defaults to false
239JOSE.JWA.supports[:jws]
240
241{:alg,
242 ["ES256", "ES384", "ES512", "Ed25519", "Ed25519ph", "Ed448", "Ed448ph",
243  "HS256", "HS384", "HS512", "PS256", "PS384", "PS512", "Poly1305", "RS256",
244  "RS384", "RS512"]}
245
246# setting unsecured_signing to true
247JOSE.unsecured_signing(true)
248
249# the "none" algorithm is now available for use
250JOSE.JWA.supports[:jws]
251
252{:alg,
253 ["ES256", "ES384", "ES512", "Ed25519", "Ed25519ph", "Ed448", "Ed448ph",
254  "HS256", "HS384", "HS512", "PS256", "PS384", "PS512", "Poly1305", "RS256",
255  "RS384", "RS512", "none"]}
256```
257
258## Usage
259
260##### JSON Web Signature (JWS) of JSON Web Token (JWT) using HMAC using SHA-256 (HS256) with JSON Web Key (JWK)
261
262_Elixir_
263
264```elixir
265# JSON Web Key (JWK)
266jwk = %{
267  "kty" => "oct",
268  "k" => :jose_base64url.encode("symmetric key")
269}
270
271# JSON Web Signature (JWS)
272jws = %{
273  "alg" => "HS256"
274}
275
276# JSON Web Token (JWT)
277jwt = %{
278  "iss" => "joe",
279  "exp" => 1300819380,
280  "http://example.com/is_root" => true
281}
282
283signed = JOSE.JWT.sign(jwk, jws, jwt)
284# {%{alg: :jose_jws_alg_hmac},
285#  %{"payload" => "eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UifQ",
286#    "protected" => "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
287#    "signature" => "shLcxOl_HBBsOTvPnskfIlxHUibPN7Y9T4LhPB-iBwM"}}
288
289compact_signed = JOSE.JWS.compact(signed)
290# {%{alg: :jose_jws_alg_hmac},
291#  "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UifQ.shLcxOl_HBBsOTvPnskfIlxHUibPN7Y9T4LhPB-iBwM"}
292
293verified = JOSE.JWT.verify(jwk, compact_signed)
294# {true,
295#  %JOSE.JWT{fields: %{"exp" => 1300819380, "http://example.com/is_root" => true,
296#     "iss" => "joe"}},
297#  %JOSE.JWS{alg: {:jose_jws_alg_hmac, :HS256}, b64: :undefined,
298#   fields: %{"typ" => "JWT"}}}
299
300verified == JOSE.JWT.verify(jwk, signed)
301# true
302```
303
304_Erlang_
305
306```erlang
307% JSON Web Key (JWK)
308JWK = #{
309  <<"kty">> => <<"oct">>,
310  <<"k">> => jose_base64url:encode(<<"symmetric key">>)
311}.
312
313% JSON Web Signature (JWS)
314JWS = #{
315  <<"alg">> => <<"HS256">>
316}.
317
318% JSON Web Token (JWT)
319JWT = #{
320  <<"iss">> => <<"joe">>,
321  <<"exp">> => 1300819380,
322  <<"http://example.com/is_root">> => true
323}.
324
325Signed = jose_jwt:sign(JWK, JWS, JWT).
326% {#{alg => jose_jws_alg_hmac},
327%  #{<<"payload">> => <<"eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UifQ">>,
328%    <<"protected">> => <<"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9">>,
329%    <<"signature">> => <<"shLcxOl_HBBsOTvPnskfIlxHUibPN7Y9T4LhPB-iBwM">>}}
330
331CompactSigned = jose_jws:compact(Signed).
332% {#{alg => jose_jws_alg_hmac},
333%  <<"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UifQ.shLcxOl_HBBsOTvPnskfIlxHUibPN7Y9T4LhPB-iBwM">>}
334
335Verified = jose_jwt:verify(JWK, CompactSigned).
336% {true,
337%     #jose_jwt{
338%         fields =
339%             #{<<"exp">> => 1300819380,
340%               <<"http://example.com/is_root">> => true,
341%               <<"iss">> => <<"joe">>}},
342%     #jose_jws{
343%         alg = {jose_jws_alg_hmac,'HS256'},
344%         b64 = undefined,
345%         fields = #{<<"typ">> => <<"JWT">>}}}
346
347Verified =:= jose_jwt:verify(JWK, Signed).
348% true
349```
350
351##### Reading JSON Web Keys (JWK) from PEM files
352
353The examples below use three keys created with `openssl`:
354
355```bash
356# RSA Private Key
357openssl genrsa -out rsa-2048.pem 2048
358
359# EC Private Key (Alice)
360openssl ecparam -name secp256r1 -genkey -noout -out ec-secp256r1-alice.pem
361
362# EC Private Key (Bob)
363openssl ecparam -name secp256r1 -genkey -noout -out ec-secp256r1-bob.pem
364```
365
366_Elixir_
367
368```elixir
369# RSA examples
370rsa_private_jwk = JOSE.JWK.from_pem_file("rsa-2048.pem")
371rsa_public_jwk  = JOSE.JWK.to_public(rsa_private_jwk)
372
373## Sign and Verify (defaults to PS256)
374message = "my message"
375signed = JOSE.JWK.sign(message, rsa_private_jwk)
376{true, ^message, _} = JOSE.JWK.verify(signed, rsa_public_jwk)
377
378## Sign and Verify (specify RS256)
379signed = JOSE.JWK.sign(message, %{ "alg" => "RS256" }, rsa_private_jwk)
380{true, ^message, _} = JOSE.JWK.verify(signed, rsa_public_jwk)
381
382## Encrypt and Decrypt (defaults to RSA-OAEP with A128CBC-HS256)
383plain_text = "my plain text"
384encrypted = JOSE.JWK.block_encrypt(plain_text, rsa_public_jwk)
385{^plain_text, _} = JOSE.JWK.block_decrypt(encrypted, rsa_private_jwk)
386
387## Encrypt and Decrypt (specify RSA-OAEP-256 with A128GCM)
388encrypted = JOSE.JWK.block_encrypt(plain_text, %{ "alg" => "RSA-OAEP-256", "enc" => "A128GCM" }, rsa_public_jwk)
389{^plain_text, _} = JOSE.JWK.block_decrypt(encrypted, rsa_private_jwk)
390
391# EC examples
392alice_private_jwk = JOSE.JWK.from_pem_file("ec-secp256r1-alice.pem")
393alice_public_jwk  = JOSE.JWK.to_public(alice_private_jwk)
394bob_private_jwk   = JOSE.JWK.from_pem_file("ec-secp256r1-bob.pem")
395bob_public_jwk    = JOSE.JWK.to_public(bob_private_jwk)
396
397## Sign and Verify (defaults to ES256)
398message = "my message"
399signed = JOSE.JWK.sign(message, alice_private_jwk)
400{true, ^message, _} = JOSE.JWK.verify(signed, alice_public_jwk)
401
402## Encrypt and Decrypt (defaults to ECDH-ES with A128GCM)
403### Alice sends Bob a secret message using Bob's public key and Alice's private key
404alice_to_bob = "For Bob's eyes only."
405encrypted = JOSE.JWK.box_encrypt(alice_to_bob, bob_public_jwk, alice_private_jwk)
406### Only Bob can decrypt the message using his private key (Alice's public key is embedded in the JWE header)
407{^alice_to_bob, _} = JOSE.JWK.box_decrypt(encrypted, bob_private_jwk)
408```
409
410_Erlang_
411
412```erlang
413% RSA examples
414RSAPrivateJWK = jose_jwk:from_pem_file("rsa-2048.pem"),
415RSAPublicJWK  = jose_jwk:to_public(RSAPrivateJWK).
416
417%% Sign and Verify (defaults to PS256)
418Message = <<"my message">>,
419SignedPS256 = jose_jwk:sign(Message, RSAPrivateJWK),
420{true, Message, _} = jose_jwk:verify(SignedPS256, RSAPublicJWK).
421
422%% Sign and Verify (specify RS256)
423SignedRS256 = jose_jwk:sign(Message, #{ <<"alg">> => <<"RS256">> }, RSAPrivateJWK),
424{true, Message, _} = jose_jwk:verify(SignedRS256, RSAPublicJWK).
425
426%% Encrypt and Decrypt (defaults to RSA-OAEP with A128CBC-HS256)
427PlainText = <<"my plain text">>,
428EncryptedRSAOAEP = jose_jwk:block_encrypt(PlainText, RSAPublicJWK),
429{PlainText, _} = jose_jwk:block_decrypt(EncryptedRSAOAEP, RSAPrivateJWK).
430
431%% Encrypt and Decrypt (specify RSA-OAEP-256 with A128GCM)
432EncryptedRSAOAEP256 = jose_jwk:block_encrypt(PlainText, #{ <<"alg">> => <<"RSA-OAEP-256">>, <<"enc">> => <<"A128GCM">> }, RSAPublicJWK),
433{PlainText, _} = jose_jwk:block_decrypt(EncryptedRSAOAEP256, RSAPrivateJWK).
434
435% EC examples
436AlicePrivateJWK = jose_jwk:from_pem_file("ec-secp256r1-alice.pem"),
437AlicePublicJWK  = jose_jwk:to_public(AlicePrivateJWK),
438BobPrivateJWK   = jose_jwk:from_pem_file("ec-secp256r1-bob.pem"),
439BobPublicJWK    = jose_jwk:to_public(BobPrivateJWK).
440
441%% Sign and Verify (defaults to ES256)
442Message = <<"my message">>,
443SignedES256 = jose_jwk:sign(Message, AlicePrivateJWK),
444{true, Message, _} = jose_jwk:verify(SignedES256, AlicePublicJWK).
445
446%% Encrypt and Decrypt (defaults to ECDH-ES with A128GCM)
447%%% Alice sends Bob a secret message using Bob's public key and Alice's private key
448AliceToBob = <<"For Bob's eyes only.">>,
449EncryptedECDHES = jose_jwk:box_encrypt(AliceToBob, BobPublicJWK, AlicePrivateJWK),
450%%% Only Bob can decrypt the message using his private key (Alice's public key is embedded in the JWE header)
451{AliceToBob, _} = jose_jwk:box_decrypt(EncryptedECDHES, BobPrivateJWK).
452```
453
454## Algorithm Support
455
456### JSON Web Encryption (JWE) [RFC 7516](https://tools.ietf.org/html/rfc7516)
457
458#### `"alg"` [RFC 7518 Section 4](https://tools.ietf.org/html/rfc7518#section-4)
459
460- [X] `A128GCMKW`
461- [X] `A192GCMKW`
462- [X] `A256GCMKW`
463- [X] `A128KW`
464- [X] `A192KW`
465- [X] `A256KW`
466- [X] `C20PKW` <sup>[draft-amringer-jose-chacha](https://tools.ietf.org/html/draft-amringer-jose-chacha-01)</sup>
467- [X] `dir`
468- [X] `ECDH-1PU`
469- [X] `ECDH-1PU+A128GCMKW` <sup>non-standard, [draft-madden-jose-ecdh-1pu](https://tools.ietf.org/html/draft-madden-jose-ecdh-1pu-02)</sup>
470- [X] `ECDH-1PU+A192GCMKW` <sup>non-standard, [draft-madden-jose-ecdh-1pu](https://tools.ietf.org/html/draft-madden-jose-ecdh-1pu-02)</sup>
471- [X] `ECDH-1PU+A256GCMKW` <sup>non-standard, [draft-madden-jose-ecdh-1pu](https://tools.ietf.org/html/draft-madden-jose-ecdh-1pu-02)</sup>
472- [X] `ECDH-1PU+A128KW` <sup>[draft-madden-jose-ecdh-1pu](https://tools.ietf.org/html/draft-madden-jose-ecdh-1pu-02)</sup>
473- [X] `ECDH-1PU+A192KW` <sup>[draft-madden-jose-ecdh-1pu](https://tools.ietf.org/html/draft-madden-jose-ecdh-1pu-02)</sup>
474- [X] `ECDH-1PU+A256KW` <sup>[draft-madden-jose-ecdh-1pu](https://tools.ietf.org/html/draft-madden-jose-ecdh-1pu-02)</sup>
475- [X] `ECDH-1PU+C20PKW` <sup>[draft-amringer-jose-chacha](https://tools.ietf.org/html/draft-amringer-jose-chacha-01), [draft-madden-jose-ecdh-1pu](https://tools.ietf.org/html/draft-madden-jose-ecdh-1pu-02)</sup>
476- [X] `ECDH-1PU+XC20PKW` <sup>[draft-amringer-jose-chacha](https://tools.ietf.org/html/draft-amringer-jose-chacha-01), [draft-madden-jose-ecdh-1pu](https://tools.ietf.org/html/draft-madden-jose-ecdh-1pu-02)</sup>
477- [X] `ECDH-ES`
478- [X] `ECDH-ES+A128GCMKW` <sup>non-standard</sup>
479- [X] `ECDH-ES+A192GCMKW` <sup>non-standard</sup>
480- [X] `ECDH-ES+A256GCMKW` <sup>non-standard</sup>
481- [X] `ECDH-ES+A128KW`
482- [X] `ECDH-ES+A192KW`
483- [X] `ECDH-ES+A256KW`
484- [X] `ECDH-ES+C20PKW` <sup>[draft-amringer-jose-chacha](https://tools.ietf.org/html/draft-amringer-jose-chacha-01)</sup>
485- [X] `ECDH-ES+XC20PKW` <sup>[draft-amringer-jose-chacha](https://tools.ietf.org/html/draft-amringer-jose-chacha-01)</sup>
486- [X] `PBES2-HS256+A128GCMKW` <sup>non-standard</sup>
487- [X] `PBES2-HS384+A192GCMKW` <sup>non-standard</sup>
488- [X] `PBES2-HS512+A256GCMKW` <sup>non-standard</sup>
489- [X] `PBES2-HS256+A128KW`
490- [X] `PBES2-HS384+A192KW`
491- [X] `PBES2-HS512+A256KW`
492- [X] `PBES2-HS512+C20PKW` <sup>non-standard</sup>
493- [X] `PBES2-HS512+XC20PKW` <sup>non-standard</sup>
494- [X] `RSA1_5`
495- [X] `RSA-OAEP`
496- [X] `RSA-OAEP-256`
497- [X] `XC20PKW` <sup>[draft-amringer-jose-chacha](https://tools.ietf.org/html/draft-amringer-jose-chacha-01)</sup>
498
499#### `"enc"` [RFC 7518 Section 5](https://tools.ietf.org/html/rfc7518#section-5)
500
501- [X] `A128CBC-HS256`
502- [X] `A192CBC-HS384`
503- [X] `A256CBC-HS512`
504- [X] `A128GCM`
505- [X] `A192GCM`
506- [X] `A256GCM`
507- [X] `C20P` <sup>[draft-amringer-jose-chacha](https://tools.ietf.org/html/draft-amringer-jose-chacha-01)</sup>
508- [X] `XC20P` <sup>[draft-amringer-jose-chacha](https://tools.ietf.org/html/draft-amringer-jose-chacha-01)</sup>
509
510#### `"zip"` [RFC 7518 Section 7.3](https://tools.ietf.org/html/rfc7518#section-7.3)
511
512- [X] `DEF`
513
514### JSON Web Key (JWK) [RFC 7517](https://tools.ietf.org/html/rfc7517)
515
516#### `"alg"` [RFC 7518 Section 6](https://tools.ietf.org/html/rfc7518#section-6)
517
518- [X] `EC`
519- [X] `oct`
520- [X] `OKP` <sup>[RFC 8037](https://tools.ietf.org/html/rfc8037)</sup>
521- [X] `OKP` with `{"crv":"Ed25519"}` <sup>[RFC 8037](https://tools.ietf.org/html/rfc8037), [RFC 8032](https://tools.ietf.org/html/rfc8032#section-5.1)</sup>
522- [X] `OKP` with `{"crv":"Ed25519ph"}` <sup>[RFC 8037](https://tools.ietf.org/html/rfc8037), [RFC 8032](https://tools.ietf.org/html/rfc8032#section-5.1)</sup>
523- [X] `OKP` with `{"crv":"Ed448"}` <sup>[RFC 8037](https://tools.ietf.org/html/rfc8037), [RFC 8032](https://tools.ietf.org/html/rfc8032#section-5.2)</sup>
524- [X] `OKP` with `{"crv":"Ed448ph"}` <sup>[RFC 8037](https://tools.ietf.org/html/rfc8037), [RFC 8032](https://tools.ietf.org/html/rfc8032#section-5.2)</sup>
525- [X] `OKP` with `{"crv":"X25519"}` <sup>[RFC 8037](https://tools.ietf.org/html/rfc8037), [RFC 7748](https://tools.ietf.org/html/rfc7748#section-5)</sup>
526- [X] `OKP` with `{"crv":"X448"}` <sup>[RFC 8037](https://tools.ietf.org/html/rfc8037), [RFC 7748](https://tools.ietf.org/html/rfc7748#section-5)</sup>
527- [X] `RSA`
528
529### JSON Web Signature (JWS) [RFC 7515](https://tools.ietf.org/html/rfc7515)
530
531#### `"alg"` [RFC 7518 Section 3](https://tools.ietf.org/html/rfc7518#section-3)
532
533- [X] `Ed25519` <sup>[RFC 8037](https://tools.ietf.org/html/rfc8037), [RFC 8032](https://tools.ietf.org/html/rfc8032#section-5.1)</sup>
534- [X] `Ed25519ph` <sup>[RFC 8037](https://tools.ietf.org/html/rfc8037), [RFC 8032](https://tools.ietf.org/html/rfc8032#section-5.1)</sup>
535- [X] `Ed448` <sup>[RFC 8037](https://tools.ietf.org/html/rfc8037), [RFC 8032](https://tools.ietf.org/html/rfc8032#section-5.2)</sup>
536- [X] `Ed448ph` <sup>[RFC 8037](https://tools.ietf.org/html/rfc8037), [RFC 8032](https://tools.ietf.org/html/rfc8032#section-5.2)</sup>
537- [X] `EdDSA` <sup>[RFC 8037](https://tools.ietf.org/html/rfc8037), [RFC 8032](https://tools.ietf.org/html/rfc8032)</sup>
538- [X] `ES256`
539- [X] `ES384`
540- [X] `ES512`
541- [X] `HS256`
542- [X] `HS384`
543- [X] `HS512`
544- [X] `Poly1305` <sup>non-standard</sup>
545- [X] `PS256`
546- [X] `PS384`
547- [X] `PS512`
548- [X] `RS256`
549- [X] `RS384`
550- [X] `RS512`
551- [X] `none` <sup>[unsecured](#footnote-unsecured)</sup>
552
553### Additional Specifications
554
555- [X] JSON Web Key (JWK) Thumbprint [RFC 7638](https://tools.ietf.org/html/rfc7638)
556- [X] JWS Unencoded Payload Option [RFC 7797](https://tools.ietf.org/html/rfc7797)
557
558<sup><a name="footnote-unsecured">unsecured</a></sup> This algorithm is disabled by default due to the unsecured signing vulnerability.  Use the [`unsecured_signing`](#unsecured-signing-vulnerability) setting to enable this algorithm.
559