Ianleeclark / Paseto

An Elixir implementation of Paseto (Platform-Agnostic Security Tokens)
Other
95 stars 8 forks source link

Paseto

CircleCI Hex.pm

This repository houses an elixir implementation of Paseto

From the reference implementation of Paseto:

What is Paseto?

Paseto (Platform-Agnostic SEcurity TOkens) is a specification and reference implementation for secure stateless tokens.

Key Differences between Paseto and JWT

Unlike JSON Web Tokens (JWT), which gives developers more than enough rope with which to hang themselves, Paseto only allows secure operations. JWT gives you "algorithm agility", Paseto gives you "versioned protocols". It's incredibly unlikely that you'll be able to use Paseto in an insecure way.

Caution: Neither JWT nor Paseto were designed for stateless session management. Paseto is suitable for tamper-proof cookies, but cannot prevent replay attacks by itself.

Considerations for using this library

There are a few library/binary requirements required in order for the Paseto library to work on any computer:

  1. Erlang version >= 20.1
    • This is required because this was the first Erlang version to introduce crypto:sign/5.
  2. libsodium >= 1.0.13
  3. openssl >= 1.1
    • This is needed for XChaCha-Poly1305 used for V2.Local Paseto

Want to use this library through Guardian or Plugs?

Check out some of my other libraries:

Paseto

Paseto Example 1

v2.local.QAxIpVe-ECVNI1z4xQbm_qQYomyT3h8FtV8bxkz8pBJWkT8f7HtlOpbroPDEZUKop_vaglyp76CzYy375cHmKCW8e1CCkV0Lflu4GTDyXMqQdpZMM1E6OaoQW27gaRSvWBrR3IgbFIa0AkuUFw.UGFyYWdvbiBJbml0aWF0aXZlIEVudGVycHJpc2Vz

This decodes to:

Paseto Example 2

v2.public.eyJleHAiOiIyMDM5LTAxLTAxVDAwOjAwOjAwKzAwOjAwIiwiZGF0YSI6InRoaXMgaXMgYSBzaWduZWQgbWVzc2FnZSJ91gC7-jCWsN3mv4uJaZxZp0btLJgcyVwL-svJD7f4IHyGteKe3HTLjHYTGHI1MtCqJ-ESDLNoE7otkIzamFskCA

This decodes to:

To learn what each version means, please see this page in the documentation.

Using Paseto (in Elixir)

Generating a token

iex> {:ok, pk, sk} = Salty.Sign.Ed25519.keypair()
iex> keypair = {pk, sk}
iex> token = Paseto.generate_token("v2", "public", "This is a test message", keypair)
"v2.public.VGhpcyBpcyBhIHRlc3QgbWVzc2FnZSe-sJyD2x_fCDGEUKDcvjU9y3jRHxD4iEJ8iQwwfMUq5jUR47J15uPbgyOmBkQCxNDydR0yV1iBR-GPpyE-NQw"

In short, we generate a keypair using libsalty2 (libsodium elixir bindings) and generate the token using that keypair.

P.S. If you're confused about how to serialize the above keys, you can use functions from the Base module:

iex> {:ok, pk, sk} = Salty.Sign.Ed25519.keypair()
iex> pk |> Base.encode16(case: :lower)
"a17c258ffdd864b3614bd445465ff96e0b16e8509e28e7ba60734f7c433ab7e8"

Parsing a token

iex> token = "v2.public.VGhpcyBpcyBhIHRlc3QgbWVzc2FnZSe-sJyD2x_fCDGEUKDcvjU9y3jRHxD4iEJ8iQwwfMUq5jUR47J15uPbgyOmBkQCxNDydR0yV1iBR-GPpyE-NQw"
iex> Paseto.parse_token(token, keypair)
{:ok,
  %Paseto.Token{
    footer: nil,
    payload: "This is a test message",
    purpose: "public",
    version: "v2"
  }}
"""

More info can be found in the HexDocs.

Installation

You need libsodium installed on your machine.

# Installing on FreeBSD
$ cd /usr/ports/security/libsodium/ && make install clean

# Installing on Ubuntu
$ sudo apt install libsodium-dev

# Installing on Fedora
$ dnf install libsodium-devel

# Redhat & Cent OS
$ yum install libsodium-devel

# Installing on OSX
$ brew install libsodium

The package can be installed by adding paseto to your list of dependencies in mix.exs:

def deps do
  [
    {:paseto, "~> 1.5.0"}
  ]
end