Thread overview
Random alphanumeric string
Jun 20, 2022
greenbyte
Jun 20, 2022
Cym13
Jan 30, 2023
Salih Dincer
Jan 31, 2023
Cym13
Jan 31, 2023
Kagamin
Jan 31, 2023
Siarhei Siamashka
Jan 30, 2023
Salih Dincer
June 20, 2022
string randomAlphanumericString(int length)
{
    import std.array : array;
    import std.ascii : letters, digits;
    import std.random : choice, Random, unpredictableSeed;
    import std.range : generate, take;
    import std.conv : to;

    auto rnd = Random(unpredictableSeed);
    auto symbols = array(letters ~ digits);

    return generate!({ return symbols.choice(rnd); }).take(length).to!string;
}
June 20, 2022

On Monday, 20 June 2022 at 11:49:24 UTC, greenbyte wrote:

>
string randomAlphanumericString(int length)
{
    import std.array : array;
    import std.ascii : letters, digits;
    import std.random : choice, Random, unpredictableSeed;
    import std.range : generate, take;
    import std.conv : to;

    auto rnd = Random(unpredictableSeed);
    auto symbols = array(letters ~ digits);

    return generate!({ return symbols.choice(rnd); }).take(length).to!string;
}

This works, but just a gentle reminder that this must not be used to generate secrets (passwords, tokens, IDs whose disclosure could be problematic...). std.random is not cryptographically secure and therefore not fit for any security-related purpose. If on the other hand you're just generating public IDs, delimiters, that sort of things, then there is absolutely no issue with doing it this way.

January 30, 2023

On Monday, 20 June 2022 at 12:40:05 UTC, Cym13 wrote:

>

This works, but just a gentle reminder that this must not be used to generate secrets (passwords, tokens, IDs whose disclosure could be problematic...). std.random is not cryptographically secure and therefore not fit for any security-related purpose.

Can you explain this a little more? Is it possible to write our own randomness algorithms or manipulate Phobos Random()?

SDB@79

January 30, 2023

It could be more flexible if it could be used as a range without packing this code too much:

auto randomAlphanumeric(string S)(size_t len)
{
  import std.array  : array;
  import std.random : choice, Random, unpredictableSeed;
  import std.range  : generate, take;

  auto rnd = Random(unpredictableSeed);
  auto gen = generate!(() => S.array.choice(rnd));

  return gen.take(len);
}

import std.ascii, std.stdio;

void main()
{

  auto str = 16.randomAlphanumeric!lowercase;
  auto hex = 16.randomAlphanumeric!hexDigits;

  foreach(c; str)
  {
    c.write;
  }
  writeln("\n", hex); /* Prints:
  tqapxlqouvbpgsia
  862C234EE3D9CFC4
*/
}

I would prefer to use an enum as it is simple. For example, it's as simple as this:

generate!(function char() => uniform!Enum)

Put that in a function and enums of type char into a struct as well:

auto randomFromEnumerate(E)(size_t len)
{
  import std.random : rnd = uniform;
  import std.range  : generate, take;

  return generate!(function char() => rnd!E).take(len);
}

struct E {
  enum num {
    o = '0', p, q, r, s, t, u, v, w, x,
  }
  enum hex {
    o = '0', p, q, r, s, t, u, v, w, x,
    a = 'A', b, c, d, e, f
  }
  enum dna {
    a = 'A', c = 'C', g = 'G', t = 'T'
  }
  enum lowercase {
    a = 'a', b, c, d, e, f, g, h, i, j, k, l,
    m, n, o, p, q, r, s, t, u, v, w, x, y, z
  }
}

void main()
{
  10.randomFromEnumerate!(E.dna).writeln;
  // CGTGAGGGTC
}

SDB@79

January 31, 2023

On Monday, 30 January 2023 at 17:13:17 UTC, Salih Dincer wrote:

>

On Monday, 20 June 2022 at 12:40:05 UTC, Cym13 wrote:

>

This works, but just a gentle reminder that this must not be used to generate secrets (passwords, tokens, IDs whose disclosure could be problematic...). std.random is not cryptographically secure and therefore not fit for any security-related purpose.

Can you explain this a little more? Is it possible to write our own randomness algorithms or manipulate Phobos Random()?

SDB@79

There are many kinds of randomness. Phobos' is good for statistical analysis and things like choosing a random name within a list for a character. It produces numbers that show no clear pattern and are spread accross a given probability distribution. Very good for statistics.

But for security you need more. Can people that see one number predict the next one? What if they see 10000 numbers? And if they cannot predict the next number, can they know what the previous one was? Do the numbers end up looping at some point?

All of these scenarios lead to exploitable vulnerabilities if present in a security context. For example if the random number is used for a website's session token then it would allow you to deduce the session token of other people by looking at your own, giving you the tool to take over their account. This is what that comment as well as the warning in the documentation of std.random are about.

I've discussed PRNG-related topics in Phobos in the past:

So how do we avoid that? There are pseudo-random generators that exist and are designed with more constraints to avoid any of the issues we mentioned and more. These are Cryptographically Secure Pseudo-Random Number Generators (CSPRNG). On linux for example /dev/urandom is such a CSPRNG. I know vibe.d exposes a CSPRNG as part of its library as well.

I would love to see a CSPRNG interface in Phobos, but at the moment it doesn't seem to be a priority (https://issues.dlang.org/show_bug.cgi?id=16493).

January 31, 2023

On Tuesday, 31 January 2023 at 06:29:24 UTC, Cym13 wrote:

>

http://breakpoint.purrfect.fr/article/cracking_phobos_uuid.html

It's not just secrecy, there's also variability requirement. A 32-bit identifier is unsuitable as an uuid, as they will repeat often.

January 31, 2023

On Tuesday, 31 January 2023 at 06:29:24 UTC, Cym13 wrote:

>

Phobos' is good for statistical analysis and things like choosing a random name
within a list for a character. It produces numbers that show no clear pattern
and are spread accross a given probability distribution. Very good for statistics.

It's good for statistics only if we ignore performance, which is actually horribly bad in std.random. Things like random array shuffling are several times slower than they could have been. Some of the Phobos problems are listed at https://github.com/libmir/mir-random#comparison-with-phobos

What would be a realistic plan to improve std.random in Phobos? Or is it a better idea to rely on third-party libraries for this functionality?

One of the actual use cases of std.random is producing deterministic randomish looking sequences for unit tests via a deterministic seed. If bounded integers generation in std.random.uniform is optimized, then these sequences will change. Also the default generator is 32-bit Mersenne Twister, which is bad for 64-bit systems because generating a random size_t index is done via producing two 32-bit numbers and gluing them together. But changing the default generator to something else will may break some applications.