MatijaL

MatijaL

How to hash a random number?

Hi,
I’m trying to hash a random number but can’t make it work…

num = Enum.random(1..9999)
hashed_num = :crypto.hash(:sha256, num)

I’m getting “1st argument: not an iodata term” error. From my understanding, Enum.random creates a number and :crypto.hash wants an iodata. The same thing happens if I use :crypto.rand_uniform(1, 9999) instead of Enum.random… can anyone help?

Marked As Solved

LostKobrakai

LostKobrakai

An integer() value is not a subtype of iodata() and even the integers allowed as part of an iolist need to be byte values, so in the range of 0..255. you likely want to encode your integer to a binary format first.

Also Liked

tangui

tangui

You can transform any term to a binary (and then hash it) with :erlang.binary_to_term/1:

iex> :erlang.term_to_binary(42)
<<131, 97, 42>>
iex> :erlang.term_to_binary(42.0)
<<131, 70, 64, 69, 0, 0, 0, 0, 0, 0>>
iex> :erlang.term_to_binary({4, 2})
<<131, 104, 2, 97, 4, 97, 2>>
soup

soup

Note that’s hashing the string “999”, not the integer 999, which might make a difference to some intentions or across application contexts. (You could argue that settling on “we always hash everything as utf8-string” as being more transportable/less-complex?)

Your hashing here is fixed width but for some things like encoding Base58 it makes a difference in payload size if nothing else.

t = DateTime.utc_now() |> DateTime.to_unix(:microsecond)

to_string_encode =
  t
  |> Integer.to_string()
  |> Base.encode64()
  |> dbg()

to_bin_encode =
  t
  |> then(fn x ->
    <<x::unsigned-integer-size(64)>>
  end)
  |> Base.encode64()
  |> dbg()

to_string_base =
  t
  # you can also pass a 2->36 (not 64!) as a base
  # this is *not* functionally the same thing though!
  |> Integer.to_string(32)
  |> dbg()

[
  to_string_encode: to_string_encode,
  to_bin_encode: to_bin_encode,
]

# the encoded string is a larger payload than the encoded integer
# => [to_string_encode: "MTY2NjQzNTI4MTAzNzU3NA==",
# =>  to_bin_encode:    "AAXrnTL3qQY="]

term_to_binary might be problematic as its leading byte is a version number (which I assume can change …) and the docs warn “There is no guarantee that this function will return the same encoded representation for the same term.”

There is an option for deterministic but it’s not x-otp version stable.

Option deterministic (introduced in OTP 24.1) can be used to ensure that within the same major release of Erlang/OTP, the same encoded representation is returned for the same term. There is still no guarantee that the encoded representation remains the same between major releases of Erlang/OTP.

That does make me wonder though, how easy is it to safely & stabley hash an actual composed data type? You could convert to some other format like json or mpack but those aren’t guaranteed to be stably ordered. I guess you’re stuck converting each value to a bitstring/hash and hashing the combination?

voltone

voltone

Or, instead of counting bits, you can just let the Erlang runtime produce the smallest binary representation of any given integer: :binary.encode_unsigned/1.

Still, I wonder what use-case is the OP had in mind: it seems to me this is building a PRNG with questionable randomness properties. If the idea is to return 32 bytes of truly random data, use :crypto.strong_rand_bytes(32). Might be faster too…

Where Next?

Popular in Questions Top

lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

Other popular topics Top

grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 54260 488
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 49266 226
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 44265 214
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

We're in Beta

About us Mission Statement