README.md

# Cryptx

This library implements SRP6a protocol.

## Installation

You should need a installed of Boost library and C++ compiler.
On Ubuntu:

```bash
sudo apt-get install build-essential
sudo apt-get install libboost-all-dev
```

Library can be installed by adding `cryptx` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:cryptx, "~> 0.0.2"}
  ]
end
```

Documentation can be found at [https://hexdocs.pm/cryptx](https://hexdocs.pm/cryptx).

## Config

```elixir
config :cryptx,
  N: "0xCBA9877884D22E11E300AAFCD3CCF019FE1D5267D14A68B92BC8767CCB7D4FD9CA53AF5CF185952AB8B6C2D269F0C0EF7D3AF4FBB85BBEFE0CBF02C7231493DDBFD134E3E25A6CD12EC683C2D10499122DD48A80DDAD417F8C2804549C0C6942C7E7AD09D72FE218051708F3609EAE955BECAF2C64C955B97ACFCC5BC17169F065449311A42264DFC64CF9BC14F4DBC38FEBE198E152560AF4265ACDD3B6086FE07E1B22DB0287391AD261A7871B5C6813D8332883DC664455A8C03B9EDBFA98C44CDBF87AEDA4AD5B4A09FE535D24098F371037778501C5DA43F3FECAABC0FF07FF617593913ADEFC14E1227FA3212195B18911EF0AB9C222F4C46644A49A7D245E6DE220DF7ECB0A83A8D547042E4E8EF27B1F6FE2CD76D955DEF109B41197EEE6D4261471D08B1F6114C9A7794187206704399DE0DC6EB11B17662531A6D52DEDDD8A2C3A430CAD8DCBDF378F6918C82E128027B46F06A32DCAF78A1210CDEDC3DA132B1C2FC50192D77A74E42EF48DC13E2E480BA42B5162F057B47E12E6CD3EDCF88ACE94DBFA602032A32793CB4C7F52C929929F2D35D905E010A7FACD094185BFD82E997558CBAAC43E7A578D13349F17CEA1B3DE10B5F886FEFB8EF25A23AF5B974A78400FC86F274823C86A7D5F6319174AB235D801939DAB9394252C3F5A94FB8E08BAD6316FEBFE62DC2BEC1E7C689164B8391A27A28587477B4D3B5AABB806098CE9817A20878E1D618FA11962FC8F30EEABF9F85AC9C3270C62E3F93B9065AE4509E9F1D55A557BEDC593738D6A7F16CE556E769D98873DDCAF3BDF4FBDC2AB597F66551D6178C95C58102B3AB2377580A0F3A092CCD0BC58C5271E867209E5BAF6E29241209717416F87306B55D6C862F5BE7EFDBE24BC77D3A8A82A0270D4C6241FF2C0C818E785552CF58E4B8748326DAEE781468D79C04EB3D35A32596941FAB111A238B6C5AAE756051C190C615C868422BAFB844FBA61FB07DC173AC2D040BE1F7A7B7E6FE28C1F57B1455A960591657A1B79E1186826FE0D721658C4C56C6817756D48C3A394D22F34E2D9ED3D9AB13EA9CB4E76476216C1C3C3FE1A21641241C5DCF11B48B123D398B114EAE0D20F294E6F98AE0E08DB495CB8468A8A21FB7F2282D649798094E0584A2E4F36777FC4D357BA954A906EC30713B9E949D109C82846457A2886F8861E24898423441A8882AAD5C5A03E79C3499F323CDF70201BCCA3CC822F1558014FDD4F58DA0B3716DD77C2076C3F0C8971890AC64D566AAC5D63A441BD1FC8ADE489248E5C54223001512317A8286F6E382E3EC38B70167FF86128B37586FF539DB1D0DC59EB7C415297250953367D8466324F60125E6449E8B04268534D686C78CA678BD1035EA6972BE5EB95F07E31E9A1761361C0DFAAE95641B10A9CBD68E001C333CA5D5C337C8DD51D8DF7",
  k: "0xbaf79a0f419d598e02aa3f2c8e94b145c4074583ed5d8a6d5af6d860f33e64168e2803914a06dabaaf5171414a39c11d4126cb4ddb8189501b3f3512508053d2",
  g: "0x2"
```

## Examples

Example out of context. So, he shows common approach.

```elixir
  require OK

  ...

  def signin(%{"login" => login, "A" => a_big}) do
    OK.for do
      user <- Accounts.fetch_user(login: login)
      {b_big, b} <- OK.success(Cryptx.compute_B(user.pw))
      b_big <- OK.success(to_string(b_big))
      b <- OK.success(to_string(b))
      u <- OK.success(Cryptx.compute_u(a_big, b_big))
      _ <- OK.required((!Cryptx.is_zero_mod_N(u)) || nil, {:reason, "zero_mod"})
      k_big <- OK.success(Cryptx.compute_K(a_big, user.pw, u, b))
    after
      key_A = key("a", login)
      key_B = key("b", login)
      key_K = key("k", login)

      Redis.set(key_A, a_big)
      Redis.set(key_B, b_big)
      Redis.set(key_K, k_big)
      Redis.expire(key_A, @session_ttl)
      Redis.expire(key_B, @session_ttl)
      Redis.expire(key_K, @session_ttl)
    end
  end

  def signin(%{"login" => login, "M" => m_big}) do
    key_A = key("a", login)
    key_B = key("b", login)
    key_K = key("k", login)

    OK.for do
      user <- Accounts.fetch_user(login: login)
      a_big <- OK.bind(Redis.get(key_A), fn x -> OK.required(x, {:reason, "session error"}) end)
      b_big <- OK.bind(Redis.get(key_B), fn x -> OK.required(x, {:reason, "session error"}) end)
      k_big <- OK.bind(Redis.get(key_K), fn x -> OK.required(x, {:reason, "session error"}) end)
      m_server <- OK.success(Cryptx.compute_M(login, user.salt, a_big, b_big, k_big))
      _ <- OK.required((m_big == m_server) || nil, {:reason, "invalid key"})
      r_server <- OK.success(Cryptx.compute_R(a_big, m_server, k_big))
    after
      {:ok, jwt, claims} = MyApp.Guardian.encode_and_sign(user)

      Redis.del(key_A)
      Redis.del(key_B)
      Redis.del(key_K)

      {:ok, %{jwt: jwt, R: r_server, user: user}}
    end
  end
```