What is the standard method for generating a nonce in Python?

前端 未结 5 1514
清歌不尽
清歌不尽 2021-02-12 12:48

Can someone share the best practices for creating a nonce for an OAuth request in Python?

相关标签:
5条回答
  • 2021-02-12 13:06

    Here's what rauth does. There's not really hard and fast rules here. The spec doesn't seem too opinionated. Your constraints are that the value, being a nonce, should be unique. Other than that, assuming the provider doesn't complain, you can use whatever method you like.

    0 讨论(0)
  • 2021-02-12 13:15

    While this probably does not exist at the time of this question creation, Python 3.6 introduced the secrets module which is meant for generating cryptographically strong random numbers suitable for managing data such as passwords, account authentication, security tokens, and related secrets.

    In this case, generating a nonce can be generated easily (here a base64 encoded string):

    nonce = secrets.token_urlsafe()
    

    Alternatives are token_bytes to get a binary token or token_hex to get an hexadecimal string.

    0 讨论(0)
  • 2021-02-12 13:18

    For most practical purposes this gives very good nonce:

    import uuid
    uuid.uuid4().hex
    # 'b46290528cd949498ce4cc86ca854173'
    

    uuid4() uses os.urandom() which is best random you can get in python.

    Nonce should be used only once and hard to predict. Note that uuid4() is harder to predict than uuid1() whereas later is more globally unique. So you can achieve even more strength by combining them:

    uuid.uuid4().hex + uuid.uuid1().hex
    # 'a6d68f4d81ec440fb3d5ef6416079305f7a44a0c9e9011e684e2c42c0319303d'
    
    0 讨论(0)
  • 2021-02-12 13:19

    Here's how python-oauth2 does it:

    def generate_nonce(length=8):
        """Generate pseudorandom number."""
        return ''.join([str(random.randint(0, 9)) for i in range(length)])
    

    They also have:

    @classmethod
    def make_nonce(cls):
        """Generate pseudorandom number."""
        return str(random.randint(0, 100000000))
    

    Additionally there is this issue entitled: "make_nonce is not random enough", which proposes:

    def gen_nonce(length):
       """ Generates a random string of bytes, base64 encoded """
       if length < 1:
          return ''
       string=base64.b64encode(os.urandom(length),altchars=b'-_')
       b64len=4*floor(length,3)
       if length%3 == 1:
          b64len+=2
       elif length%3 == 2:
          b64len+=3
       return string[0:b64len].decode()
    

    And also references CVE-2013-4347. TL;DR version, use os.urandom or the abstracted interface to it (SystemRandom).

    I like my lambdas—and didn't want non-alphanumeric characters—so I used this:

    lambda length: filter(lambda s: s.isalpha(), b64encode(urandom(length * 2)))[:length]
    
    0 讨论(0)
  • 2021-02-12 13:22

    Here are a few ideas I got for emailage. The generate_nonce comes from their code, but I use generate_nonce_timestamp which I used uuid for. It gives me a random alpha-numeric string and a time stamp in seconds:

    import random
    import time
    import uuid
    
    
    def generate_nonce(length=8):
        """Generate pseudo-random number."""
        return ''.join([str(random.randint(0, 9)) for i in range(length)])
    
    
    def generate_timestamp():
        """Get seconds since epoch (UTC)."""
        return str(int(time.time()))
    
    def generate_nonce_timestamp():
        """Generate pseudo-random number and seconds since epoch (UTC)."""
        nonce = uuid.uuid1()
        oauth_timestamp, oauth_nonce = str(nonce.time), nonce.hex
        return oauth_nonce, oauth_timestamp
    

    I like using uuid1, since it generates the uuid based on current host and time and has the time property that you can extract if you need both. For emailage, you need both the timestamp and the nonce.

    Here is what you get:

    >>> generate_nonce_timestamp()
    ('a89faa84-6c35-11e5-8a36-080027c336f0', '136634341422770820')
    

    If you want to remove the -, use nonce.get_hex().

    uuid1 - Generate a UUID from a host ID, sequence number, and the current time. More on uuid.

    0 讨论(0)
提交回复
热议问题