Giter Club home page Giter Club logo

strap's Introduction

Strap - SRP6/6a (Secure Remote Password) for Elixir

This is a simple module that helps you implement the Secure Remote Password (SRP) protocol in Elixir applications. For more information about SRP, see the design documents and RFC5054.

Build Status Hex.pm Version

Installation

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

def deps do
  [
    {:strap, "~> 0.1.1"}
  ]
end

If you're running inside of a Phoenix application, you may need to ensure the Erlang crypto application is loaded.

def application do
  [
    extra_applications: [
      :logger,
      :crypto
    ]
  ]
end

Documentation

The HexDocs.pm documentation is available here.

SRP Flow

A typical SRP request/response flow looks like this:

  1. Client gets username/password from user

  2. Client -> Server: Client sends the username to the server.

  3. Server looks up the user's information, from a database for example. This information would be the prime, generator, salt, and so-called verifier value for this user. Optionally, if the server doesn't know this user, it may return/calculate fake values to obscure the user's lack-of-presence.

  4. Server generates a public value, based on the prime, generator, verifier, and an ephemeral randomly-generated private value only it knows.

  5. Server -> Client: Server sends the prime, generator, salt, and public value back to the client.

  6. Client generates a public value, based on the prime, generator, and an ephemeral randomly-generated private value only it knows.

  7. Client -> Server: Client sends its public value to the server.

  8. Server generates a pre-shared master key based upon the information it has.

  9. Client generates a pre-shared master key based upon the information it has.

The server and client should, at this point, verify that their pre-shared master keys match. For example, the client could send a HMAC(key, server-public-key) to the server, and the server could send HMAC(key, client-public-key) back to the client.

Altenatively, if the preshared key will be utilized for further encrypted communication, not just authentication, the server and the client can simply exchange encrypted messages using an agreed-upon cipher (e.g. AES-256). A failure to decrypt messages indicates a lack of knowledge of the preshared key.

Usage

This library helps with steps 4, 6, 8, and 9, above. An example flow might look like:

# Client

username = get_username()
private_client_password = get_password()

# Server

# Fetch verifier and salt from database
{salt, private_server_verifier} = get_salt_and_verifier(username)
# Use "known-good" prime/generator; could also be stored in database
{prime, generator} = Strap.prime_group(2048)

server =
  Strap.protocol(:srp6a, prime, generator)
  |> Strap.server(verifier)

server_public_value = Strap.public_value(server)

# Client

client =
  Strap.protocol(:srp6a, prime, generator)
  |> Strap.client(username, private_client_password, salt)

client_public_vlaue = Strap.public_value(client)

# Server

{:ok, private_server_session_key} =
  Strap.session_key(server, client_public_value)

# Client

{:ok, private_client_session_key} =
  Strap.session_key(client, server_public_value)

# At this point, the following should be true:

^private_server_session_key = private_client_session_key

strap's People

Contributors

twooster avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

mtrudel hoffi

strap's Issues

Cant get example from readme working

Hey, sorry to bother ya, but I was trying to get the example from the readme working using gen_tcp, and it looks like im getting two different session keys for the client and the server. Ive looked over my code dozens of times and I swear im doing exactly what youre showing in the readme. Could you look this over and let me know if im missing something?

I have it split up into 2 files, client.ex and server.ex

Client.ex

    {:ok, data} = :gen_tcp.recv(socket, 0)
    # IO.puts "Recieved data from node: #{data}"

    [prime, generator, salt, server_public_value] = String.split(data, "|")

    IO.puts "Prime: #{prime}"
    IO.puts "Generator: #{generator}"
    IO.puts "Salt: #{salt}"
    IO.puts "Server Pub: #{server_public_value}"

    {:ok, prime} = Base.decode64(prime)
    {:ok, server_public_value} = Base.decode64(server_public_value)
    {generator, _} = Integer.parse(generator)

    client =
      Strap.protocol(:srp6a, prime, generator)
      |> Strap.client("Alex", "somepassword", salt)

    client_public_value = Strap.public_value(client)

    IO.puts "Client Pub: #{Base.encode64(client_public_value)}"

    {:ok, private_client_session_key} = Strap.session_key(client, server_public_value)

    IO.puts "private_client_session_key = #{Base.encode64(private_client_session_key)}"

    :ok = :gen_tcp.send(socket, Base.encode64(client_public_value))

Server.ex:

{:ok, socket} = :gen_tcp.accept(listen_socket)

    verifier = "AnotherPass"
    salt = "mysalt"
    {prime, generator} = Strap.prime_group(2048)

    server =
      Strap.protocol(:srp6a, prime, generator)
      |> Strap.server(verifier)

    server_public_value = Strap.public_value(server)

    IO.puts "Prime: #{Base.encode64(prime)}"
    IO.puts "Generator: #{Integer.to_string(generator)}"
    IO.puts "Salt: #{salt}"
    IO.puts "Server Pub: #{Base.encode64(server_public_value)}"

    response =
      [Base.encode64(prime), Integer.to_string(generator), salt, Base.encode64(server_public_value)]
      |> Enum.reduce(fn x, acc -> acc <> "|" <> x end)

    # IO.puts "Accepted connection from client."
    :ok = :gen_tcp.send(socket, response)

    {:ok, data} = :gen_tcp.recv(socket, 0)
    # IO.puts "Recieved data: '#{data}'"

    IO.puts "Client Pub: #{data}"

    {:ok, client_public_value} = Base.decode64(data)

    {:ok, private_server_session_key} =
      Strap.session_key(server, client_public_value)

    IO.puts "PRIVATE SESSION KEY = #{Base.encode64(private_server_session_key)}"

The output of each are:

Prime: rGvbQTJKmpvxZt5eE4lYL69ytmUZh+4H/DGSlD21YFCjcynLtKCZ7YGT4HV3Z6E91SMSq0sDMQ3Nf0ip2gT9UOgIOWntt2ewz2CVF5oWOrNmGgX71fqq6CkYqZYvC5O4Vfl5k+yXXuqoDXQK2/T/dHNZ0EHVwz6nHSgeRGsUdzvKl7Q6I/uAFna9IHpDbGSB8dK5B4cXRhpbnTLmiPh3SFRFI7UksNV9Xqd6J3XS7PoDLPvb9S+zeGFgJ5AE5Xrmr4dOcwPOUymczAQce8MI2CpWmPOo0MOCca41+Onb+7aUtcgD2J965DXeI21SX1R1m2XjcvzWjvIPpxEfnkr/cw==
Generator: 2
Salt: mysalt
Server Pub: bjc4JJmA+zg2DRRULHvcsFide0FXEc2kz1aNaRYMo6MBPvxaiKH3krgT/kUPQkshThIqHhX4uDGgNXfNgEhURwCobzyKgH0gq+3Km35i3IiLSkjvpRCx+XLAxdPngJ+O7i5ysh9ehszeLIY9kU3H7UEnMH9U67rxa/3fhIjR0LGqGMy4iFj7roJ9Ku9ONQxcutbtFp8MZ9BHWochm4ZerRsfzeLO6lhtLMKB61MozXFMMblojSZd6AEOV+JQIfSRw1DkMMXoEqI48n22grXt+9yxc8184GoElQb+f0gYd6vPVGpaBaZbWL9qw00v1SKbV79fAkodqWoRmsPhrk/azg==
Client Pub: CkrVJHFbk9jj/8zYsOdt/QLmxReXBilzzma9jBgKxk7WzOOdE21ebaaxk5pRKcXSOzD5mIe+pCMVLYeYJvMduh/C8D0Ea+xQUdwyon7QnNzepROCEn+2bV58febMibFmKvn3ETmISP0IyPP6NJzFbeQlxrxdeab7uRsxCwTjippaKRfth2LNamJVWyEBWsv0x5br9ANL66i6WUfnZkRlMel24I9wZS2vfMGEcc6Nwpb/EZ11ph7p8qRjHU+0HzXBGrKjwxXOIi/hQPHbJPiejITb2PN3MkHVXhJbqXN1eNO9c+rTmqwucMSOoCkucvs7PPhN1HZAJhk/HsUcYZlK7Q==
PRIVATE SESSION KEY = RgeFL5crUQ9SLR5m0QefWBok24VD5EPffQ3CN6NTJ2mEGl74iCdwBO8wVvaNwis/G1w0hvHXRRzz/haFK7HjYSu3HCEEBXZKg0xH/+/lelFiij7mCRAvSUrtOJqJGwcI7+RE4iBPwQmnAF9kNyzQcTnMsdyCrJAYhORAdelK9xT12mehayJSHYaOUqOSoAAF4+m6xB3ZOO8dlQpeCrdGrZJQ4VBSAhCxUkMsy3oV3UQybJpfp3Z+u+tobsGPOvTREFPKPt1y1Aqc4smpCNfNWxM6LXHCT5hYm7UMSXYGNN6ztiC7p08SXwnjZcwBDLj5deCYytNYBm02bDXEsOQSDA==

and

Prime: rGvbQTJKmpvxZt5eE4lYL69ytmUZh+4H/DGSlD21YFCjcynLtKCZ7YGT4HV3Z6E91SMSq0sDMQ3Nf0ip2gT9UOgIOWntt2ewz2CVF5oWOrNmGgX71fqq6CkYqZYvC5O4Vfl5k+yXXuqoDXQK2/T/dHNZ0EHVwz6nHSgeRGsUdzvKl7Q6I/uAFna9IHpDbGSB8dK5B4cXRhpbnTLmiPh3SFRFI7UksNV9Xqd6J3XS7PoDLPvb9S+zeGFgJ5AE5Xrmr4dOcwPOUymczAQce8MI2CpWmPOo0MOCca41+Onb+7aUtcgD2J965DXeI21SX1R1m2XjcvzWjvIPpxEfnkr/cw==
Generator: 2
Salt: mysalt
Server Pub: bjc4JJmA+zg2DRRULHvcsFide0FXEc2kz1aNaRYMo6MBPvxaiKH3krgT/kUPQkshThIqHhX4uDGgNXfNgEhURwCobzyKgH0gq+3Km35i3IiLSkjvpRCx+XLAxdPngJ+O7i5ysh9ehszeLIY9kU3H7UEnMH9U67rxa/3fhIjR0LGqGMy4iFj7roJ9Ku9ONQxcutbtFp8MZ9BHWochm4ZerRsfzeLO6lhtLMKB61MozXFMMblojSZd6AEOV+JQIfSRw1DkMMXoEqI48n22grXt+9yxc8184GoElQb+f0gYd6vPVGpaBaZbWL9qw00v1SKbV79fAkodqWoRmsPhrk/azg==
Client Pub: CkrVJHFbk9jj/8zYsOdt/QLmxReXBilzzma9jBgKxk7WzOOdE21ebaaxk5pRKcXSOzD5mIe+pCMVLYeYJvMduh/C8D0Ea+xQUdwyon7QnNzepROCEn+2bV58febMibFmKvn3ETmISP0IyPP6NJzFbeQlxrxdeab7uRsxCwTjippaKRfth2LNamJVWyEBWsv0x5br9ANL66i6WUfnZkRlMel24I9wZS2vfMGEcc6Nwpb/EZ11ph7p8qRjHU+0HzXBGrKjwxXOIi/hQPHbJPiejITb2PN3MkHVXhJbqXN1eNO9c+rTmqwucMSOoCkucvs7PPhN1HZAJhk/HsUcYZlK7Q==
private_client_session_key = R1qtcn4F+2kR2JSLF3PdrNUl4UK+FovvUets60xqwdtbdT7wjC48rvKc5UUu/1nY2cYINlb/0gRswSg9DGiAHAk6qYFpEi3UYUP2F4cPv6B4r2EhIkrETosbRYxxpJuadlhioGna1NQCDT24ha4fqmGrRJ985rK0XmEp14t9OsgavW6lYBmRaClAdnAw5UvlzpJ+TvslTgS/BK2fZ7nHiqQ7DP37SBEvabQhsYf+VmzPeTtJmlq38X951fe6yn65DzV+Bz5EojgYBOYCvt3tt1Bdo0xVNWtRrT0LhmmChMcM8AKq9YPfacKHFCdtk+qUR/EE+JHqvoR1LUwCkstndQ==

It seems to me like everything is getting passed around correctly, just the actual session keys vary.

Project Status

@twooster I'm wondering if you're still willing to take PRs / release hex packages against this repo? I ask because I've added support for M1 / M2 creation on top of Strap and I'd love to include it in the library. However, since I'm using Strap as a dependency for a hex package I'm authoring and mix requires that all transitive dependencies be published hex packages, it's a dead end working up a PR if it isn't going to get published. Hoping for confirmation before I work it up into a PR.

Thanks!

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.