Creating a never-repeating random hexadecimal gene

2019-09-14 20:58发布

问题:

My company has asked me to develop a 4-byte random hexadecimal generator for some security hardware we have, however I am new to this sort of thing. (To clarify, each code consists of 4 hexadecimal digits).

We currently have a list of 124 hexadecimals that are in use and I need to be able to not repeat those hexadecimals as well as ones that will be generated with this program. I have developed a GUI and a generator, I just need help making sure it never repeats.

This is what I have so far:

# 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:

Your question asks about a 4-byte random hexadecimal generator, but in the comments you clarify that you only want 4 hex digits, which means there are only 2**16 combinations. That makes the problem rather easy: we just create a list of all 65,536 combinations and shuffle it, and then we can simply iterate over that shuffled list. To save a little time & RAM I create a list of integers & just convert the integers to hex strings as needed.

The fact that you've got a list of 124 codes that are already in use adds a little bit of complexity, but we can handle that by putting those codes into a set; we can easily test the generated codes to see if they're in the used set.

Obviously, we want to be able to run the program multiple times, so we save the index number of the shuffled list into a text file. This is simpler and more efficient than storing each number that we generate into the used set.

We also need the randomization to be consistent, so we need to supply a seed to the random number generator.

Here's some Python 3 code. It can be adapted to run on Python 2 (by changing FileNotFoundError to IOError), but you cannot switch versions between runs because the sequence of random numbers generated by Python 2 will not be the same as that generated by 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))

output from 3 runs

Using index 0
Code: d0fc
Saving index 1

Using index 1
Code: d7e9
Saving index 3

Using index 3
Code: fc42
Saving index 4

As you can see, index 2 gets skipped, that's because it corresponds to a code in the used set.



标签: python random