Search code examples
twitterrandomd

Generate Random Alphanumeric String in D


I'm looking for a platform independent way to generate a random alphanumeric string for a Twitter nonce. Currently I'm using this but it depends on /dev/random which is obviously UNIX-specific:

private auto _getNonce() {
    ubyte[32] buffer;
    File devRandom  = File("/dev/random", "rb");
    auto randomData = devRandom.rawRead(buffer);
    auto randomBase = Base64.encode(randomData);

    auto nonWords   = regex(r"[\W_]", "g");
    return replaceAll(randomBase, nonWords, "");
}

This follows the recommendation in the Twitter development documentation to get 32 bytes of random data, base-64 encode them and strip all non-alphanumeric characters.

The nonce doesn't have to be cryptographically secure, it's just used to prevent duplicate submissions. Any suggestions for a better way to do this which works on Windows as well as UNIX?


Solution

  • Note: After all these years I should point out that randomCover does not repeat. Meaning this solution will only provide a character once in lower case and once in upper case. I looked at using cycle() to remedy this but randomCover doesn't support infinite ranges.

    If all you need is 32 alphnumeric characters:

    import std.algorithm : fill;
    import std.ascii : letters, digits;
    import std.conv : to;
    import std.random : randomCover, rndGen;
    import std.range : chain;
    import std.stdio : writeln;
    
    void main() {
        // dchar[] are random access, strings (char[]) are not
        auto asciiLetters = to!(dchar[])(letters);
        auto asciiDigits = to!(dchar[])(digits);
    
        dchar[32] key;
        fill(key[], randomCover(chain(asciiLetters, asciiDigits), rndGen));
        writeln(key);
    }
    

    The range documentation specifically states

    static assert(!isNarrowString!R); // narrow strings cannot be indexed as ranges

    narrow strings being char[] and wchar[]. While they are arrays, one cannot find "character" 2,531 in O(1) preventing these types from being considered random access, which is required by randomCover.