Giter Site home page Giter Site logo

siwe-ex's Introduction

Sign-In with Ethereum

Elixir library to enable Sign-In with Ethereum message validation.

Full documentation found at https://hexdocs.pm/siwe.

This library provides functions for parsing and validating SIWE message strings and their corresponding signatures.

Requirements:

Elixir at version 1.10 or higher using OTP 23 or greater. Rustler officially supports the last 3 minor versions of Elixir, which we also suggest for best experience.

A Rust compiler at version 1.56 or higher so that 2021 edition libraries can be compiled.

Installation

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

def deps do
  [
    {:siwe, "~> 0.3"}
  ]
end

Example

To see how this works in iex, clone this repository and from the root run:

$ mix deps.get

Then create two files message.txt:

login.xyz wants you to sign in with your Ethereum account:
0xfA151B5453CE69ABf60f0dbdE71F6C9C5868800E

Sign-In With Ethereum Example Statement

URI: https://login.xyz
Version: 1
Chain ID: 1
Nonce: ToTaLLyRanDOM
Issued At: 2021-12-17T00:38:39.834Z

signature.txt:

0x8d1327a1abbdf172875e5be41706c50fc3bede8af363b67aefbb543d6d082fb76a22057d7cb6d668ceba883f7d70ab7f1dc015b76b51d226af9d610fa20360ad1c

then run

$ iex -S mix

Once in iex, you can then run the following to see the result:

iex> {:ok, msg} = File.read("./message.txt")
...
iex> {:ok, sig} = File.read("./signature.txt")
...
iex> Siwe.parse_if_valid(String.trim(msg), String.trim(sig))
{:ok, %{
  __struct__: Siwe,
  address: "0xfA151B5453CE69ABf60f0dbdE71F6C9C5868800E",
  chain_id: "1",
  domain: "login.xyz",
  expiration_time: nil,
  issued_at: "2021-12-17T00:38:39.834Z",
  nonce: "ToTaLLyRanDOM",
  not_before: nil,
  request_id: nil,
  resources: [],
  statement: "Sign-In With Ethereum Example Statement",
  uri: "https://login.xyz",
  version: "1"
}}

Any valid SIWE message and signature pair can be substituted.The functions described below can also be tested with msg, sig, or a value set to the result Siwe.parse_if_valid.

API Overview

This library deals with three different types of input:

  1. SIWE message strings.
  2. Signatures of SIWE message strings.
  3. A parsed SIWE message which is defined as:
  defmodule Message do
    defstruct domain: "",
      address: "",
      statement: "",
      uri: "",
      version: "",
      chain_id: "",
      nonce: "",
      issued_at: "",
      expiration_time: nil, # or a string datetime
      not_before: nil, # or a string datetime
      request_id: nil, # or string
      resources: []
  end

The most basic functions are parse and to_str which translate a SIWE message string to a parsed SIWE message and back (respectively). To simplify using the variables from the above example:

iex> {:ok, parsed} = Siwe.parse(String.trim(msg))
...
iex> {:ok, str2} = Siwe.to_str(parsed) 
iex> str2 == String.trim(msg)
:true

Once parsed, the Message can be verified.

  • verify_sig takes the Message and a corresponding signature and returns true if the Message's address field would produce the signature if it had signed the Message's string form.

  • verify returns true if verify_sig would and current time is after the Message's not_before field (if it exists) and before the Message's expiration_time field (if it exists). Three optional string parameters can be passed to verify:

    • domain_binding, which Message.domain must match to pass verification
    • match_nonce, which Message.nonce must match to pass verification
    • timestamp, which will instead verify the message at that point in time
iex> Siwe.verify_sig(parsed, String.trim(sig))
:true
iex> Siwe.verify(parsed, String.trim(sig), "login.xyz", nil, nil)
:true
iex> Siwe.verify(parsed, String.trim(sig), nil, "12341234", nil)
:true
iex> Siwe.verify(parsed, String.trim(sig), nil, nil, "2021-04-04T00:38:39.834Z")
:true
iex> Siwe.verify(parsed, String.trim(sig), nil, nil, nil)
:true

parse_if_valid is an optimized helper function which takes a SIWE message string and a signature then returns a parsed Message only if the signature matches and the current time is after the Message's not_before field (if it exists) and before the Message's expiration_time field (if it exists).

iex> Siwe.generate_nonce()
"EaLc76FkngQ"

Another helper, generate_nonce function is provided to create alphanumeric [a-z, A-Z, 1-9] nonces compliant with SIWE's spec, used like so: This is useful for servers using SIWE for their own authentication systems.

Disclaimer

Our Elixir library for Sign-In with Ethereum has not yet undergone a formal security audit. We welcome continued feedback on the usability, architecture, and security of this implementation.

See Also

siwe-ex's People

Contributors

karlosmid avatar krhoda avatar obstropolos avatar theosirian avatar

Forkers

metalink-app

siwe-ex's Issues

switch to rustler_precompiled

To use rustler_precompiled in an Elixir project, you need to follow these steps:

Add rustler_precompiled as a dependency in your mix.exs file. Update the deps function as follows:
elixir
Copy code
defp deps do
[
{:rustler_precompiled, "~> 0.22"}
]
end
In your Elixir code, define a Rust module and declare the NIF functions using rustler_precompiled. Here's an example:
elixir
Copy code
defmodule MyRustModule do
use Rustler.Precompiled

Define the NIF functions

defnif add(a, b), do: :rustler_precompiled.add(a, b)
defnif subtract(a, b), do: :rustler_precompiled.subtract(a, b)
end
In this example, we define two NIF functions, add and subtract, which are wrappers around the Rust NIF functions implemented in Rust.

In your mix.exs file, add the configuration for rustler_precompiled in the project function:
elixir
Copy code
def project do
[
...
compilers: Mix.compilers() ++ [:rustler_precompiled],
rustler_precompiled: [crate_path: "path/to/your/rust/project"],
...
]
end
Replace "path/to/your/rust/project" with the actual path to your Rust project. This configuration tells rustler_precompiled where to find your Rust project and compile it into a NIF.

Build your Elixir project by running mix compile. This will compile both your Elixir code and the Rust code.

Load and use the Rust NIF functions in your Elixir code. Here's an example usage:

elixir
Copy code
a = 5
b = 3

result = MyRustModule.add(a, b)
IO.puts("Result of adding #{a} and #{b} is: #{result}")

result = MyRustModule.subtract(a, b)
IO.puts("Result of subtracting #{b} from #{a} is: #{result}")
In this example, we call the add and subtract functions from the MyRustModule module, which internally invokes the Rust NIF functions implemented using rustler_precompiled.

Run your Elixir code using mix run or start your application using mix run --no-halt or iex -S mix.
By following these steps, you can integrate rustler_precompiled and use Rust NIFs in your Elixir project. Make sure to have Rust installed on your system and properly configure the Rust project and module names in the Elixir code. For more information and advanced usage, refer to the rustler_precompiled documentation and examples.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.