如何创建一个黑客证明唯一代码

时间:2016-09-22 17:37:21

标签: algorithm

我正在制作一系列独特的代码,以便投放宣传广告系列。 该活动将运行总计2000万个独特项目。代码的有效期为一年。我目前正在寻找最好的选择。 我只能在代码中使用0-9和A-Z.所以限制我在我的代码中使用36个唯一字符。最终用户需要键入系统中的唯一CD并获得优惠。唯一代码不会与任何用户或交易相关联。

生成唯一代码的一种方法是创建增量数字,然后将它们转换为base36以获得唯一的CD。这个问题是它易于破解。用户可以开始以增量方式插入unqiue cd并兑换不适合他们的优惠。我正在考虑引入某种随机化。需要有关相同的建议。

注意 - 代码中的最大字符数限制为8.

2 个答案:

答案 0 :(得分:5)

使用加密强随机数生成器生成40位数(即5字节随机数组的序列)。将每个数组转换为base-36将产生一系列随机八字符代码。对每个代码运行额外检查以确保没有重复项。在转换后的字符串上使用哈希集可以让您在合理的时间内执行此任务。

以下是Java中的示例实现:

Set<String> codes = new HashSet<>();
SecureRandom rng = new SecureRandom();
byte[] data = new byte[5];
for (int i = 0 ; i != 100000 ; i++) {
    rng.nextBytes(data);
    long val = ((long)(data[0] & 0xFF))
    | (((long)(data[1] & 0xFF)) << 8)
    | (((long)(data[2] & 0xFF)) << 16)
    | (((long)(data[3] & 0xFF)) << 24)
    | (((long)(data[4] & 0xFF)) << 32);
    String s = Long.toString(val, 36);
    codes.add(s);
}
System.out.println("Generated "+codes.size()+" codes.");

Demo.

答案 1 :(得分:0)

使用Guid(C#代码):

string code = Guid.NewGuid().ToString().Substring(0,8).ToUpperInvariant();

由于我们有十六进制表示,因此我们得到数字和字符af。我们得到16 ^ 8个可能的代码,其> 40亿个代码。每两个代码中就有214个代码。

Guid.NewGuid().ToString()会产生类似"6b984c2f-5866-4745-ac34-d5088a56070f"的字符串。由于第一组的长度为8个字符,因此我们可以将前8个字符转换为大写字母。结果看起来像"6B984C2F"

请注意,这可能会产生重复的代码。我们可以这样避免:

var codes = new HashSet<string>();
while (codes.Count < 20000000) {
    string code = Guid.NewGuid().ToString().Substring(0,8).ToUpperInvariant();
    codes.Add(code);
}

HashSet允许您多次添加项目,但始终只保留其中一项。 (就像数学一样。)

如果您想使用全范围的可能值,则上面的单行不会这样做。使用整个字母加数字,我们得到36 ^ 8 = ~2.8 * 10 ^ 12个可能的代码。对于2000万个代码,每141,055个一个。那更好但仍然没有完全破解证据。您需要限制输入尝试次数,使用CAPTCHA等。

const string Base = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const int CodeLength = 8;
const int NumCodes = 20000000;

var random = new Random();
var codes = new HashSet<string>();
var chars = new char[CodeLength];
while (codes.Count < NumCodes) {
    for (int i = 0; i < CodeLength; i++) {
        int pos = random.Next(Base.Length);
        chars[i] = Base[pos];
    }
    string code = new string(chars);
    codes.Add(code);
}