Generating non-repeating random numbers in Python

前端 未结 17 1763
粉色の甜心
粉色の甜心 2020-11-30 19:56

Ok this is one of those trickier than it sounds questions so I\'m turning to stack overflow because I can\'t think of a good answer. Here is what I want: I need Python to ge

17条回答
  •  孤独总比滥情好
    2020-11-30 20:31

    If you don't need something cryptographically secure, but just "sufficiently obfuscated"...

    Galois Fields

    You could try operations in Galois Fields, e.g. GF(2)32, to map a simple incrementing counter x to a seemingly random serial number y:

    x = counter_value
    y = some_galois_function(x)
    
    • Multiply by a constant
      • Inverse is to multiply by the reciprocal of the constant
    • Raise to a power: xn
    • Reciprocal x-1
      • Special case of raising to power n
      • It is its own inverse
    • Exponentiation of a primitive element: ax
      • Note that this doesn't have an easily-calculated inverse (discrete logarithm)
      • Ensure a is a primitive element, aka generator

    Many of these operations have an inverse, which means, given your serial number, you can calculate the original counter value from which it was derived.

    As for finding a library for Galois Field for Python... good question. If you don't need speed (which you wouldn't for this) then you could make your own. I haven't tried these:

    • NZMATH
    • Finite field Python package
    • Sage, although it's a whole environment for mathematical computing, much more than just a Python library

    Matrix multiplication in GF(2)

    Pick a suitable 32×32 invertible matrix in GF(2), and multiply a 32-bit input counter by it. This is conceptually related to LFSR, as described in S.Lott's answer.

    CRC

    A related possibility is to use a CRC calculation. Based on the remainder of long-division with an irreducible polynomial in GF(2). Python code is readily available for CRCs (crcmod, pycrc), although you might want to pick a different irreducible polynomial than is normally used, for your purposes. I'm a little fuzzy on the theory, but I think a 32-bit CRC should generate a unique value for every possible combination of 4-byte inputs. Check this. It's quite easy to experimentally check this, by feeding the output back into the input, and checking that it produces a complete cycle of length 232-1 (zero just maps to zero). You may need to get rid of any initial/final XORs in the CRC algorithm for this check to work.

提交回复
热议问题