diff --git a/README.md b/README.md index bb30887..0d16439 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Examples showing how to do many things in Gleam! ## Cryptography - [Hashing data](./universal/test/cryptography/hashing_data.gleam) +- [Hashing passwords](./universal/test/cryptography/hashing_passwords.gleam) (Erlang) ## Data structures diff --git a/erlang/gleam.toml b/erlang/gleam.toml index e4fc3da..a2721d5 100644 --- a/erlang/gleam.toml +++ b/erlang/gleam.toml @@ -5,6 +5,7 @@ target = "erlang" [dependencies] gleam_stdlib = ">= 0.34.0 and < 2.0.0" youid = ">= 1.2.0 and < 2.0.0" +argus = ">= 1.0.1 and < 2.0.0" [dev-dependencies] gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/erlang/manifest.toml b/erlang/manifest.toml index 7363f76..3b06d7a 100644 --- a/erlang/manifest.toml +++ b/erlang/manifest.toml @@ -2,14 +2,17 @@ # You typically do not need to edit this file packages = [ + { name = "argus", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "jargon"], otp_app = "argus", source = "hex", outer_checksum = "8AD8E412B8A7223A2393CA09F8D54A0FC62CB3D4D6BBDF40635C904F9EC1C82C" }, { name = "gleam_crypto", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "ADD058DEDE8F0341F1ADE3AAC492A224F15700829D9A3A3F9ADF370F875C51B7" }, { name = "gleam_erlang", version = "0.26.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "3DF72F95F4716883FA51396FB0C550ED3D55195B541568CAF09745984FD37AD1" }, { name = "gleam_stdlib", version = "0.40.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "86606B75A600BBD05E539EB59FABC6E307EEEA7B1E5865AFB6D980A93BCB2181" }, { name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" }, + { name = "jargon", version = "1.0.0", build_tools = ["rebar3"], requirements = [], otp_app = "jargon", source = "hex", outer_checksum = "60FBFACC920EAEBC96C76DA3D8ED814FABDDC2103CC0D04FE314A3C15F3174DF" }, { name = "youid", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_stdlib"], otp_app = "youid", source = "hex", outer_checksum = "EF0F693004E221155EE5909C6D3C945DD14F7117DBA882887CF5F45BE399B8CA" }, ] [requirements] +argus = { version = ">= 1.0.1 and < 2.0.0" } gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" } gleeunit = { version = ">= 1.0.0 and < 2.0.0" } youid = { version = ">= 1.2.0 and < 2.0.0" } diff --git a/erlang/test/cryptography/hashing_passwords.gleam b/erlang/test/cryptography/hashing_passwords.gleam new file mode 100644 index 0000000..30e1d4f --- /dev/null +++ b/erlang/test/cryptography/hashing_passwords.gleam @@ -0,0 +1,49 @@ +//// # Hashing passwords +//// +//// The argus library has bindings to the standard C implementation of the +//// argon2 password hashing algorithm. This is the best option for password +//// hashing presently. Currently it only supports Erlang. +//// +//// Because argus depends on C code you will need to ensure that the computers +//// you compile your project on have a C compiler and Make installed. +//// +//// ## Dependencies +//// +//// - https://hex.pm/packages/argus + +import argus +import gleeunit/should + +pub fn main_test() { + let password = "blink182" + + // The `hash` function can be used to hash a password with a salt. + // + // A SALT MUST NEVER BE REUSED. Generate a new one for each password you + // need to hash. + let assert Ok(hashes) = + argus.hasher() + |> argus.hash(password, argus.gen_salt()) + + // The `verify` function is used to check a password against a hash. + argus.verify(hashes.encoded_hash, password) + |> should.equal(Ok(True)) + + argus.verify(hashes.encoded_hash, "some-other-password") + |> should.equal(Ok(False)) + + // Password hashing is a (deliberately) expensive operation. + // If you are hashing passwords frequently in your test suite you may want to + // configure the hasher to be less expensive to run. + // + // NEVER DO THIS OUTSIDE OF TESTS. You must do your research before setting + // any of these values and ensure you know what you are doing. + let assert Ok(_hashes) = + argus.hasher() + |> argus.algorithm(argus.Argon2id) + |> argus.time_cost(3) + |> argus.memory_cost(12_228) + |> argus.parallelism(1) + |> argus.hash_length(32) + |> argus.hash("password", argus.gen_salt()) +}