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?
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.