PythonでOAuthリクエストのナンスを作成するためのベストプラクティスを誰かが共有できますか?
5 に答える
これはこの質問の作成時にはおそらく存在しませんが、Python 3.6では、パスワード、アカウント認証、セキュリティトークン、関連するシークレットなどのデータの管理に適した暗号的に強力な乱数を生成するためのシークレットモジュールが導入されました。
この場合、ナンスの生成は簡単に生成できます(ここではbase64でエンコードされた文字列)。
nonce = secrets.token_urlsafe()
代替手段は、バイナリトークンを取得するためのtoken_bytes、または16進文字列を取得するためのtoken_hexです。
ほとんどの実用的な目的のために、これは非常に良いナンスを与えます:
import uuid
uuid.uuid4().hex
# 'b46290528cd949498ce4cc86ca854173'
uuid4()
os.urandom()
Pythonで取得できる最もランダムなものを使用します。
ノンスは一度だけ使用する必要があり、予測するのは困難です。後者はよりグローバルにユニークであるのに対し、それはuuid4()
予測するのが難しいことに注意してください。uuid1()
したがって、それらを組み合わせることで、さらに強力なものを実現できます。
uuid.uuid4().hex + uuid.uuid1().hex
# 'a6d68f4d81ec440fb3d5ef6416079305f7a44a0c9e9011e684e2c42c0319303d'
python-oauth2の実行方法は次のとおりです。
def generate_nonce(length=8):
"""Generate pseudorandom number."""
return ''.join([str(random.randint(0, 9)) for i in range(length)])
彼らも持ってる:
@classmethod
def make_nonce(cls):
"""Generate pseudorandom number."""
return str(random.randint(0, 100000000))
さらに、「 make_nonceは十分にランダムではありません」というタイトルのこの問題があります。
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()
また、 CVE-2013-4347も参照しています。TL; DRバージョン、使用os.urandom
、またはそれへの抽象化されたインターフェース(SystemRandom)。
私は自分のsが好きで、lambda
英数字以外の文字は必要なかったので、次のように使用しました。
lambda length: filter(lambda s: s.isalpha(), b64encode(urandom(length * 2)))[:length]
これがrauthの機能です。ここには、それほど厳格で迅速なルールはありません。スペックはあまり意見が分かれていないようです。制約は、ナンスである値が一意である必要があるということです。それ以外は、プロバイダーが文句を言わないことを前提として、あなたは好きな方法を使うことができます。
これが私がメールで得たいくつかのアイデアです。generate_nonceはそれらのコードから取得されますが、uuidを使用したgenerate_nonce_timestampを使用します。ランダムな英数字の文字列とタイムスタンプが秒単位で表示されます。
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
私はuuid1を使用するのが好きです。これは、現在のホストと時刻に基づいてuuidを生成し、両方が必要な場合に抽出できるtimeプロパティを備えているためです。電子メールの場合、タイムスタンプとナンスの両方が必要です。
これがあなたが得るものです:
>>> generate_nonce_timestamp()
('a89faa84-6c35-11e5-8a36-080027c336f0', '136634341422770820')
を削除する場合は-
、を使用しますnonce.get_hex()
。
uuid1-ホストID、シーケンス番号、および現在の時刻からUUIDを生成します。uuidの詳細。