创建一个永不重复的随机十六进制生成器

时间:2017-01-30 14:07:44

标签: python random

我的公司要求我为我们拥有的一些安全硬件开发一个4字节的随机十六进制生成器,但我是这类新手。 (为了澄清,每个代码由4个十六进制数字组成)。

我们目前有一个正在使用的124个十六进制列表,我需要能够不重复这些十六进制以及将使用该程序生成的十六进制。我开发了一个GUI和一个生成器,我只需要帮助确保它永远不会重复。

这是我到目前为止所做的:

# random hexadecimal generator engine 
text = "" 

for i in range(4): 
    rand = random.choice('0123456789abcdef') 
    text = text + rand 
    print(text) 

# creating the window 
root = Tk() # GUI window 
root.title("Hex Generator") 
root.geometry("250x150") 
app = Frame(root) 
app.grid() 
label = Label(app, text="Click to generate a Hexadecimal") 
button1 = Button(app, text="Generate") 
label.grid() 
button1.grid() 
label1 = Label(app, text=text) 
label1.grid() 

# kicking off event loop 
root.mainloop()

1 个答案:

答案 0 :(得分:2)

您的问题询问了一个4字节的随机十六进制生成器,但在评论中您澄清了您只需要4个十六进制数字,这意味着只有2**16个组合。这使问题变得相当简单:我们只创建一个包含所有65,536个组合的列表并对其进行混洗,然后我们可以简单地遍历该混洗列表。节省一点时间& RAM我创建一个整数列表&只需根据需要将整数转换为十六进制字符串。

你有一个已经使用的124个代码的列表这一事实增加了一点点复杂性,但我们可以通过将这些代码放入一个集合来处理它;我们可以轻松测试生成的代码,看看它们是否在used集中。

显然,我们希望能够多次运行程序,因此我们将混洗列表的索引号保存到文本文件中。这比将我们生成的每个数字存储到used集中更简单,更有效。

我们还需要随机化一致,因此我们需要为随机数生成器提供种子。

这是一些Python 3代码。它可以适用于在Python 2上运行(通过将FileNotFoundError更改为IOError),但不能在运行之间切换版本,因为Python 2生成的随机数序列将与Python 3生成的不一样

from random import seed, shuffle

passphrase = 'My secret passphrase'
seed(passphrase)

# Codes that were already in use. 
# This list could be read from a file instead of being embedded in the script 
used = '''\
2b2d
40a7
c257
d929
c252
5805
2936
8b20
'''

# Convert to a set of strings
used = set(used.splitlines())

# The index of the next number to generate is stored in this file
fname = 'nextindex.txt'

try:
    with open(fname) as f:
        idx = int(f.read())
except FileNotFoundError:
    idx = 0

print('Using index', idx)

allnums = list(range(0x10000))
shuffle(allnums)

#Search for the next code that's not in the `used` set
while True:
    hexcode = format(allnums[idx], '04x')
    idx += 1
    if hexcode not in used:
        print('Code:', hexcode)
        break

# Save the next index
with open(fname, 'w') as f:
    print('Saving index', idx)
    f.write(str(idx))

3次输出

Using index 0
Code: d0fc
Saving index 1

Using index 1
Code: d7e9
Saving index 3

Using index 3
Code: fc42
Saving index 4

如您所见,索引2被跳过,这是因为它对应于used集中的代码。