Current section
Files
Jump to
Current section
Files
lib/setaria.ex
defmodule Setaria do
@moduledoc """
## Setaria
Setaria is OATH One Time Passwords Library for Elixir.
This is wrapper of [POT](https://hex.pm/packages/pot).
NOTE: Some parameters are fixed now. The timestep is 30, digits is 6, and digest method is sha.
"""
@default_timestep 30
# hotp
@doc """
Create HOTP with base32 encoded secret and counter.
"""
@spec hotp(String.t, Integer.t) :: String.t
def hotp(encoded_secret, counter) do
:pot.hotp(encoded_secret, counter)
end
@doc """
Create HOTP with raw secret and counter.
"""
@spec hotp(String.t, Integer.t, Keyword.t) :: String.t
def hotp(raw_secret, counter, encoded_secret: false) do
encoded_secret = Base.encode32(raw_secret, padding: false)
hotp(encoded_secret,counter)
end
# hotp validation
@doc """
Validate HOTP with base32 encoded secret and counter.
"""
@spec valid_hotp(String.t, String.t, Integer.t) :: boolean
def valid_hotp(token, encoded_secret, counter) do
:pot.valid_hotp(token, encoded_secret, [{:last, counter - 1}]) == counter
end
@doc """
Validate HOTP with raw secret and counter.
"""
@spec valid_hotp(String.t, String.t, Integer.t, Keyword.t) :: boolean
def valid_hotp(token, raw_secret, counter, encoded_secret: false) do
encoded_secret = Base.encode32(raw_secret, padding: false)
valid_hotp(token, encoded_secret, counter)
end
# totp
@doc """
Create TOTP with base32 encoded secret and current timestamp.
"""
@spec totp(String.t) :: String.t
def totp(encoded_secret) do
timestamp = System.system_time(:seconds)
totp(encoded_secret, timestamp)
end
@doc """
Create TOTP with raw secret and current timestamp.
"""
@spec totp(String.t, Keyword.t) :: String.t
def totp(raw_secret, encoded_secret: false) do
encoded_secret = Base.encode32(raw_secret, padding: false)
totp(encoded_secret)
end
@doc """
Create TOTP with base32 encoded secret and timestamp.
"""
@spec totp(String.t, integer) :: String.t
def totp(encoded_secret, timestamp) do
counter = get_counter_from_timestamp(timestamp, @default_timestep)
hotp(encoded_secret, counter)
end
@doc """
Create TOTP with raw secret and timestamp.
"""
@spec totp(String.t, integer, Keyword.t) :: String.t
def totp(raw_secret, timestamp, encoded_secret: false) do
encoded_secret = Base.encode32(raw_secret, padding: false)
totp(encoded_secret, timestamp)
end
# totp validation
@doc """
Validate TOTP with token, base32 encoded secret and current timestamp.
"""
@spec valid_totp(String.t, String.t) :: boolean
def valid_totp(token, encoded_secret) do
timestamp = System.system_time(:seconds)
counter = get_counter_from_timestamp(timestamp, @default_timestep)
valid_hotp(token, encoded_secret, counter)
end
@doc """
Validate TOTP with token, raw secret and current timestamp.
"""
@spec valid_totp(String.t, String.t, Keyword.t) :: boolean
def valid_totp(token, raw_secret, encoded_secret: false) do
encoded_secret = Base.encode32(raw_secret, padding: false)
valid_totp(token, encoded_secret)
end
@doc """
Validate TOTP with token, base32 encoded secret and timestamp.
"""
@spec valid_totp(String.t, String.t, integer) :: boolean
def valid_totp(token, encoded_secret, timestamp) do
counter = get_counter_from_timestamp(timestamp, @default_timestep)
valid_hotp(token, encoded_secret, counter)
end
@doc """
Validate TOTP with token, raw secret and timestamp.
"""
@spec valid_totp(String.t, String.t, integer, Keyword.t) :: boolean
def valid_totp(token, raw_secret, timestamp, encoded_secret: false) do
encoded_secret = Base.encode32(raw_secret, padding: false)
valid_totp(token, encoded_secret, timestamp)
end
defp get_counter_from_timestamp(timestamp, timestep) do
trunc(timestamp / timestep)
end
end