argon2id_elixir/lib/argon2_elixir.ex

116 lines
2.9 KiB
Elixir
Raw Permalink Normal View History

2024-11-09 14:06:34 +02:00
defmodule Argon2 do
@moduledoc """
2024-11-09 15:23:09 +02:00
Argon2 password hashing using Rust.
2024-11-09 14:06:34 +02:00
2024-11-09 15:23:09 +02:00
This module provides a secure way to hash passwords using the Argon2i algorithm.
2024-11-09 14:06:34 +02:00
2024-11-09 15:54:33 +02:00
## Installation
Add `argon2` to your list of dependencies in `mix.exs`:
```
def deps do
[
{:argon2id_elixir, "~> 1.1.1"}
]
end
```
Ensure you have Rust installed, as it's required for compilation:
```sh
# On Windows
winget install Rust.Rust
# On Unix-like systems (https://rustup.rs/)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
2024-11-09 14:06:34 +02:00
## Security Presets
* `:owasp` (default) - OWASP recommended settings (m=19456, t=2, p=1)
* `:strong` - Higher security settings (m=65540, t=3, p=4)
## Examples
# Hash with default OWASP settings
iex> hash = Argon2.hash_password("secure_password123")
iex> String.starts_with?(hash, "$argon2i$v=19$m=19456,t=2,p=1$")
true
# Hash with strong settings
iex> hash = Argon2.hash_password("secure_password123", "strong")
iex> String.starts_with?(hash, "$argon2i$v=19$m=65540,t=3,p=4$")
true
# Verify password
iex> hash = Argon2.hash_password("secure_password123")
iex> Argon2.verify_password("secure_password123", hash)
true
iex> Argon2.verify_password("wrong_password", hash)
false
## Security Notes
* Passwords must be at least 8 characters long
* Each hash uses a unique random salt
"""
@type password :: String.t()
@type hash :: String.t()
@type config :: String.t()
@doc """
Hashes a password using Argon2i.
## Options
2024-11-09 15:23:09 +02:00
* `config` - One of `"owasp"` (default) or `"strong"`
2024-11-09 14:06:34 +02:00
## Examples
iex> hash = Argon2.hash_password("secure_password123")
iex> is_binary(hash)
true
## Security Notes
* Passwords must be at least 8 characters
* A unique random salt is used for each hash
* The default OWASP preset is recommended for most use cases
Raises `ArgumentError` if the password is less than 8 characters long.
"""
@spec hash_password(password :: password, config :: config | nil) :: hash
def hash_password(password, config \\ nil) do
case Argon2.Native.hash_password(password, config) do
{:error, message} -> raise ArgumentError, message
result -> result
end
end
@doc """
Verifies a password against a hash.
Takes constant time regardless of whether the password matches or not.
## Examples
iex> hash = Argon2.hash_password("secure_password123")
iex> Argon2.verify_password("secure_password123", hash)
true
Raises `ArgumentError` if:
* The password is less than 8 characters long
* The hash format is invalid
"""
@spec verify_password(password :: password, hash :: hash) :: boolean
def verify_password(password, hash) do
case Argon2.Native.verify_password(password, hash) do
{:error, message} -> raise ArgumentError, message
result -> result
end
end
end