在D中生成随机字母数字字符串

时间:2013-11-23 11:35:59

标签: twitter random d

我正在寻找一种独立于平台的方法来为Twitter随机数生成随机字母数字字符串。目前我正在使用它,但它取决于/dev/random,这显然是特定于UNIX的:

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, "");
}

这跟随the recommendation in the Twitter development documentation获得32字节的随机数据,base-64编码它们并删除所有非字母数字字符。

nonce不必是加密安全的,它只是用来防止重复提交。有关更好的方法可以在Windows和UNIX上运行的任何建议吗?

2 个答案:

答案 0 :(得分:6)

注意:经过这么多年,我应该指出randomCover不重复。这意味着此解决方案仅提供一次小写字符和一次大写字符。我查看了使用cycle()来解决此问题,但randomCover不支持无限范围。

如果您只需要32个字母数字字符:

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);
}

range documentation具体说明

  

static assert(!isNarrowString!R); //窄字符串不能作为范围索引

窄字符串是char []和wchar []。虽然它们是数组,但是在O(1)中找不到“字符”2,531,这阻止了这些类型被认为是randomCover所需的随机访问。

答案 1 :(得分:3)

std.random应该可以正常工作。如果您关心使用的类型,它有各种随机数生成器,但std.random.rndGen使用Mt19937,这是Mersenne Twister MT19937的实现。 std.random的数字生成器是范围,这使得它们与其他Phobos的交互非常好。

一种可能的实施方式

string genNonce()
{
    import std.algorithm, std.ascii, std.base64, std.conv, std.random, std.range;

    auto rndNums = rndGen().map!(a => cast(ubyte)a)().take(32);

    auto result = appender!string();
    Base64.encode(rndNums, result);

    return result.data.filter!isAlphaNum().to!string();
}

rndGen()生成无限范围的随机数。 map!(a => cast(ubyte)a)()然后懒洋洋地将它们转换为ubyte。并且take(32)懒惰地获取它们中的前32个,以便结果范围的长度为32而不是无穷大。然后使用Base64.encode对输出范围内的值进行编码,并对其进行过滤,使其仅包含字母数字字符并转换为string