首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >(安全)随机字符串?

(安全)随机字符串?
EN

Stack Overflow用户
提问于 2011-02-17 22:01:18
回答 3查看 9.6K关注 0票数 11

在Lua中,通常使用math.random & math.randomseed生成随机值和/或字符串,其中os.time用于math.randomseed

然而,这种方法有一个主要缺点:返回的数总是和当前的时间一样随机,每个随机数的间隔是1秒,如果一个人在很短的时间内需要很多随机值,那就太长了。

Lua用户wiki:http://lua-users.org/wiki/MathLibraryTutorial甚至指出了这个问题,并指出了相应的RandomStringS receipe:http://lua-users.org/wiki/RandomStrings

所以我坐下来写了一种不同的算法(如果可以这样的话),它使用表的内存地址生成随机数:

代码语言:javascript
复制
math.randomseed(os.time())
function realrandom(maxlen)
    local tbl = {}
    local num = tonumber(string.sub(tostring(tbl), 8))
    if maxlen ~= nil then
        num = num % maxlen
    end
    return num
end

function string.random(length,pattern)
    local length = length or 11
    local pattern = pattern or '%a%d'
    local rand = ""
    local allchars = ""
    for loop=0, 255 do
        allchars = allchars .. string.char(loop)
    end
    local str=string.gsub(allchars, '[^'..pattern..']','')
    while string.len(rand) ~= length do
        local randidx = realrandom(string.len(str))
        local randbyte = string.byte(str, randidx)
        rand = rand .. string.char(randbyte)
    end

    return rand
end

一开始,一切看起来都是随机的,我相信它们是.至少现在的计划是这样。

我的问题是,realrandom返回的这些数字有多大的随机性?

或者,是否有更好的方法在短于1秒的时间内生成随机数(如上面所解释的那样,哪种方式意味着不应该使用os.time ),而不依赖外部库,如果可能的话,使用完全跨平台的方式?

编辑:

对于RNG的种子方式,似乎存在一个重大的误解;在生产代码中,对math.randomseed()的调用只发生一次,这只是一个错误的例子。

我所说的随机值是每秒随机一次,很容易通过下面的粘贴来演示:http://codepad.org/4cDsTpcD

由于这个问题将被否决,无论我的编辑,我也取消了我以前接受的答案-希望一个更好的答案,即使只是更好的意见。我知道关于随机值/数字的问题以前已经讨论过很多次了,但我没有发现这样一个问题可能与Lua相关--请记住这一点!

EN

回答 3

Stack Overflow用户

发布于 2011-02-17 23:14:44

  1. --您不应该每次调用随机时都调用seed,您应该在程序初始化时只调用它一次(除非您从某个地方获得种子,例如,复制以前的“随机”行为)。
  2. 标准Lua随机生成器在统计意义上质量很差(事实上,它是标准C随机生成器),如果您关心它,就不要使用它。例如,使用lrandom模块(可在LuaRocks中获得)。
  3. 如果您需要更安全的随机,请从Linux上的/dev/random中读取。(我认为Windows应该有类似的东西--但您可能需要用C语言编写代码才能使用它。)
  4. 依赖表指针值是个坏主意。例如,考虑一下Java中的备用Lua实现--不知道它们会返回什么。(此外,指针值可能是可预测的,而且在某些情况下,每次调用程序时指针值可能是相同的。)
  5. 如果您想要更好的种子精度(而且只有在以每秒一次以上的频率启动程序时,您才需要这样做),那么您应该使用分辨率更好的定时器。例如,socket.gettime()来自LuaSocket。将其乘以某个值,因为math.randomseed只处理整数部分,而socket.gettime()以(浮点)秒为单位返回时间。 要求‘套接字’math.randomseed(socket.gettime() * 1e6)为i= 1,1e3为打印(math.random())端
票数 7
EN

Stack Overflow用户

发布于 2011-02-18 12:39:15

然而,这种方法有一个主要缺点:返回的数总是和当前时间一样随机,每个随机数的间隔是1秒,如果一个人在很短的时间内需要许多随机值,那么这个间隔就太长了。

只有当你不正确地实现它时,它才有这些弱点。

math.randomseed应该被谨慎地调用--通常在程序开始时只调用一次,并且它通常是使用os.time的种子。一旦设置了种子,您就可以多次使用math.random,它将产生随机值。

看看这个示例发生了什么:

代码语言:javascript
复制
> math.randomseed(1)
> return math.random(), math.random(), math.random()
0.84018771715471    0.39438292681909    0.78309922375861
> math.randomseed(2)
> return math.random(), math.random(), math.random()
0.70097636929759    0.80967634907443    0.088795455214007
> math.randomseed(1)
> return math.random(), math.random(), math.random()
0.84018771715471    0.39438292681909    0.78309922375861

当我把种子从1变2时,我得到了不同的随机结果。但当我回到1,“随机序列”被重置。我得到了和以前一样的值。

os.time()返回一个不断增加的数字。使用它作为种子是合适的;然后您可以永远调用math.random,并且每次调用它时都有不同的随机数。

唯一需要担心非随机性的情况是,程序应该每秒执行不止一次。在这种情况下,正如其他人所说,最简单的解决方案是使用一个定义更高的时钟。

换言之:

  • 在程序开始时使用一个批准的种子(os.time()在99%的情况下)调用os.time()
  • 每次需要随机数时都调用math.random

致以问候!

票数 4
EN

Stack Overflow用户

发布于 2011-02-17 22:27:38

我想到了几件重要的事情:

  • 在大多数其他语言中,您通常只在程序开始时调用随机的“种子”函数一次,或者在整个执行过程中调用有限的时间。您通常不希望每次生成随机数/序列时都调用它。如果在程序启动时调用它一次,就可以绕过“每秒一次”的限制。通过每次调用它,您的结果可能最终会以较少的随机性结束。
  • 您的rely ()函数似乎依赖于Lua的一个私有实现细节。在下一个主要版本中,如果这个细节更改为总是返回相同的数字,或者只返回偶数,等等.仅仅因为它现在起作用是不够有力的保证,特别是在需要安全的RNG的情况下。
  • 当你说“一切看起来都是完全随机的”时,你是如何衡量这种表现的?我们人类很难判断一个序列是随机的还是不随机的,仅仅看一串数字实际上是不可能真正判断它们是否随机的。有许多方法来量化一个系列的“随机性”,包括频率分布、自相关、压缩,还有许多超出我理解的范围。
  • 如果您正在为生产编写一个真正的“安全PRNG”,请不要编写您自己的!通过多年/几十年的研究、设计和试图打破图书馆或算法的专家,调查和使用一个库或算法。真正安全的随机数生成是困难的。

如果您需要更多信息,请从维基百科的PRNG文章开始,并根据需要使用那里的参考资料/链接。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5035229

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档