From 3cdb9039b359ef7e19e2093062909e140320994c Mon Sep 17 00:00:00 2001 From: Andrei Mihu Date: Sat, 24 Oct 2015 21:18:59 +0100 Subject: [PATCH] Default to strong PRNG for UUID4, allow weak if explicitly requested. Closes #9. --- .travis.yml | 5 +++-- CHANGELOG.md | 4 ++++ README.md | 12 +++++++++--- lib/uuid.ex | 32 +++++++++++++++++++++++++++++++- mix.exs | 2 +- mix.lock | 4 ++-- 6 files changed, 50 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 192f655..442cd96 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: elixir elixir: -- 1.0.4 +- 1.0.5 otp_release: -- 17.1 +- 18.0 +sudo: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 110c22c..f8b473a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ None. --- +### v1.1.0, 24 Oct 2015, Elixir `~> 1.0` + +* [Enhancement] `uuid4` now accepts an additional first argument `:strong` (default) or `:weak`, indicating whether to use strong PRNG or not. + ### v1.0.1, 30 May 2015, Elixir `~> 1.0` * [Internal] Use `:os.timestamp/1` instead of `:erlang.now/1`. diff --git a/README.md b/README.md index 0bcb75b..cf60cf3 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,12 @@ UUID generator and utilities for [Elixir](http://elixir-lang.org/). See [RFC 412 ### Installation -The latest version is `1.0.1` and requires Elixir `~> 1.0`. New releases may change this minimum compatible version depending on breaking language changes. The [changelog](https://github.com/zyro/elixir-uuid/blob/master/CHANGELOG.md) lists every available release and its corresponding language version requirement. +The latest version is `1.1.0` and requires Elixir `~> 1.0`. New releases may change this minimum compatible version depending on breaking language changes. The [changelog](https://github.com/zyro/elixir-uuid/blob/master/CHANGELOG.md) lists every available release and its corresponding language version requirement. Releases are published through [hex.pm](https://hex.pm/packages/uuid). Add as a dependency in your `mix.exs` file: ```elixir defp deps do - [ { :uuid, "~> 1.0" } ] + [ { :uuid, "~> 1.1" } ] end ``` @@ -37,11 +37,14 @@ iex> UUID.uuid3("5976423a-ee35-11e3-8569-14109ff1a304", "my.domain.com") ### UUID v4 -Generated based on pseudo-random bytes. +Generated based on pseudo-random bytes. Accepts optional `:strong` (default) or `:weak` parameter. ```elixir iex> UUID.uuid4() "fcfe5f21-8a08-4c9a-9f97-29d2fd6a27b9" + +iex> UUID.uuid4(:weak) +"cd63a9c4-0b4e-477a-8229-3f3aa971a37b" ``` ### UUID v5 @@ -81,6 +84,9 @@ iex> UUID.uuid5(:dns, "my.domain.com", :default) ```elixir iex> UUID.uuid4(:hex) "19be859d0c1f4a7f95ddced995037350" + +iex> UUID.uuid4(:weak, :hex) +"ebeff765ddc843e486c287fb668d5d37" ``` `:urn` is a standard UUID representation prefixed with the UUID URN: diff --git a/lib/uuid.ex b/lib/uuid.ex index 86a5cc0..5b04e77 100644 --- a/lib/uuid.ex +++ b/lib/uuid.ex @@ -261,29 +261,59 @@ defmodule UUID do Generate a new UUID v4. This version uses pseudo-random bytes generated by the `crypto` module. + Accepts optional `:strong` (default) or `:weak` parameter. + ## Examples ```elixir + # Equivalent to: UUID.uuid4(:strong, :default) iex> UUID.uuid4() "fb49a0ec-d60c-4d20-9264-3b4cfe272106" + # Equivalent to: UUID.uuid4(:strong, :default) + iex> UUID.uuid4(:strong) + "fb49a0ec-d60c-4d20-9264-3b4cfe272106" + + # Equivalent to: UUID.uuid4(:weak, :default) + iex> UUID.uuid4(:weak) + "cd63a9c4-0b4e-477a-8229-3f3aa971a37b" + + # Equivalent to: UUID.uuid4(:strong, :default) iex> UUID.uuid4(:default) "fb49a0ec-d60c-4d20-9264-3b4cfe272106" + # Equivalent to: UUID.uuid4(:strong, :hex) iex> UUID.uuid4(:hex) "fb49a0ecd60c4d2092643b4cfe272106" + # Equivalent to: UUID.uuid4(:strong, :urn) iex> UUID.uuid4(:urn) "urn:uuid:fb49a0ec-d60c-4d20-9264-3b4cfe272106" + iex> UUID.uuid4(:weak, :urn) + "urn:uuid:cd63a9c4-0b4e-477a-8229-3f3aa971a37b" ``` """ - def uuid4(format \\ :default) do + def uuid4(), do: uuid4(:strong, :default) + + def uuid4(:strong), do: uuid4(:strong, :default) + def uuid4(:weak), do: uuid4(:weak, :default) + def uuid4(format), do: uuid4(:strong, format) + + def uuid4(:strong, format) do + <> = :crypto.strong_rand_bytes(16) + <> + |> uuid_to_string format + end + def uuid4(:weak, format) do <> = :crypto.rand_bytes(16) <> |> uuid_to_string format end + def uuid4(_, _) do + raise ArgumentError, message: "Invalid argument; Expected :strong|:weak" + end @doc """ Generate a new UUID v5. This version uses an SHA1 hash of fixed value (chosen diff --git a/mix.exs b/mix.exs index d6fa4b5..b708426 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule UUID.Mixfile do def project do [app: :uuid, name: "UUID", - version: "1.0.1", + version: "1.1.0", source_url: "https://github.com/zyro/elixir-uuid", homepage_url: "http://hexdocs.pm/uuid", elixir: "~> 1.0", diff --git a/mix.lock b/mix.lock index ccc3845..ae6730f 100644 --- a/mix.lock +++ b/mix.lock @@ -1,3 +1,3 @@ %{"benchfella": {:hex, :benchfella, "0.2.1"}, - "earmark": {:hex, :earmark, "0.1.17"}, - "ex_doc": {:hex, :ex_doc, "0.8.4"}} + "earmark": {:hex, :earmark, "0.1.18"}, + "ex_doc": {:hex, :ex_doc, "0.10.0"}}