英文:
Can I rely on Go's `crypto/rand` package to give me unique random string?
问题
我想生成32个字符长的“唯一”且“不可猜测”的字母数字秘钥。这个秘钥将作为我的系统标识符,并用于查找信息。
在搜索网络时,我偶然发现了Go语言的crypto/rand
包。该包能够通过底层系统调用生成随机的字母数字组合。但我担心crypto/rand
包返回的值可能会在后续产生非唯一的字符串。
有人能否澄清一下我是否可以依赖crypto/rand
包来完成这个任务?
英文:
I want to generate 32 characters long unique
unguessable
alphanumeric secret keys. The secret key will be an identifier for my system and will be used to look up information.
While searching the web I stumbled upon the crypto/rand
package of Go
. Which is able to generate random alphanumerics with the help of underline system calls. But I am concerned that the value returned by the crypto/rand
package might produce a non-unique string down the line.
Can anyone clarify if I can rely on the crypto/rand
package for the job?
答案1
得分: 5
当然,对于随机生成的令牌,总是存在生成重复令牌的可能性。有一些标准,比如UUID(不包括v4),使用其他方法来尝试“保证”每个标识符的唯一性。这些方法并不能真正消除碰撞的可能性,它们只是转移了故障模式。例如,UUID1依赖于MAC地址的唯一性,这本身就是一个问题。
如果你的令牌大小没有限制,你可以轻松地选择足够大的位数,使得碰撞的概率变得非常小,完全被无数其他故障模式所淹没(比如程序员错误、宇宙射线、大规模全球灭绝事件等)。
非常粗略地说,如果你有一个真正的随机密钥长度为N位,那么在出现50%碰撞的机会之前,你可以生成2^(N/2)个密钥。请参考维基百科上的UUID#Collisions页面,了解更一般的公式。
英文:
Of course with randomly generated tokens, there is always the possibility of generating a duplicate token. There are standards such as UUID (excluding v4) that use other methods to try to "guarantee" uniqueness of each identifier. These methods do not truly obviate the possibility of collisions, they just shift the failure modes. For example, UUID1 relies on uniqueness of MAC addresses, which is a whole issue of its own.
If you are not limited by the size of your tokens, you can easily pick a sufficiently large number of bits that the probability of collisions becomes so small that it is completely dwarfed by countless other failure modes (such as programmer error, cosmic rays, a mass global extinction event, etc.).
Very approximately, if you have a true random key length of N bits, you can generate 2^(N/2) keys before having a 50% chance of seeing collisions. See the Wikipedia page for UUID#Collisions for a more general formula.
答案2
得分: 4
我认为,对于这种类型的事情,你应该使用UUID
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
id := uuid.New()
fmt.Println(id.String())
}
英文:
I think, for this type of thing, you should use UUID
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
id := uuid.New()
fmt.Println(id.String())
}
答案3
得分: 3
使用crypto/rand模块时,不能保证每个随机数都不会重复出现。尽管这种情况发生的概率非常低,但对于您的用例来说可能已经足够了。在许多情况下,UUID可能已经足够好了。如果您对UUID重复出现的概率感兴趣,可以参考Wikipedia上的相关信息。
如果您真的需要真正的唯一性,您可以将随机数与一个记录它们的映射表结合起来,其中随机数作为键,值是一个"不关心"的占位符。在记录随机数时,可以检测到重复项,并在需要时请求一个新的随机数。然而,这种方法可能会引入新的挑战,取决于您的设置,因为这些数字现在保存在内存中,本身就是不安全的。如果您的用例不能确定系统生命周期内所需的密钥数量,这也将在复杂性方面带来挑战。
对我来说,关键问题在于您用于信息查找的系统标识符是否真的是机密信息,或者您只是希望在系统中出现之前很难预测的唯一标识符。也许您可以详细说明您的用例,以澄清您的需求。
英文:
With crypto/rand there is no guarantee that individual random numbers will occur more than once. The probability of this to happen is very low, however, and it may be good enough for your use case. In many cases UUID will be good enough. If you are curious about the probability of duplicate UUIDs, see Wikipedia for example.
If you really need true uniqueness you may want to combine random numbers with a map to record them, where the number serves as key and the value is a "don't care". While recording the numbers, duplicates can be detected and a new random can be requested in case. However, this approach may introduce a new challenge depending on your setting as the numbers are now kept in memory which is insecure per se. It will also be challenging in terms of complexity if your use case does not determine the quantity of secrets required during the lifetime of the system.
For me, it really boils down to the question whether the identifiers for your system you use for info lookups are really secrets or you just want unique identifiers which are hard to predict before they occur in the system. Maybe you can elaborate on your use case to clarify your requirements.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论